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