スレッド間通信でchannelを使う(@Rust)

Rustの場合にはchannelを使わなくても、メモリ管理がきちんとされているのでmutexでも良さそうなのですが、channelの方が使うのは簡単だと思う。ほぼGolangと同等の機能ですが、rx/txを同時に定義するのは異なります。Golangは -> もしくは <- でインアウトを切り替えるし、channelのサイズも指定しますが、RustではFIFOのように動作します。

以下のコードは、

https://isehara-3lv.sakura.ne.jp/blog/2023/10/06/並行処理rust/

にスレッド起動後にスレッドの番号をchannelに送るようにしたもの。一点注意すべきはtxはmainスレッド中で生成されているので、for received in rx処理はdrop(tx)しないと無限待ちになること。もしクロージャー中ならば、そのライフが終わった時点でdrop()されますが。

use std::thread;
use std::time::Duration;
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();
    let mut handles = Vec::new();
    for i in 0..3 {
        let thread_tx = tx.clone();
        let handle = thread::spawn(move || {
            for j in 1..10 {
                println!("hi number {} {} from the spawned thread!", i, j);
                thread::sleep(Duration::from_millis(1));
            }
            thread_tx.send(i).unwrap();
        });
        handles.push(handle);
    }

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }

    for handle in handles {
        handle.join().unwrap();
    }

    drop(tx);       // without drop(), this program doesn't terminate, wait for tx forever

    for received in rx {
        println!("Got from the threads : {}", received);
    }

}

出力の最後部分だけ、

~~~~~~
hi number 0 9 from the spawned thread!
hi number 2 9 from the spawned thread!
Got from the threads : 0
Got from the threads : 1
Got from the threads : 2

P.S. 同じスレッド間での通信になっていたので修正(2023/10/11)

送信エンドポイントはclone()しないとコンパイルが通りません(moveしたものをdrop()はできないから)。clone()して複数の送信エンドポイントから送信でもrxに集約されるようです。

 

admin

カテゴリーRust