やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rustのスレッド(メッセージ送受信)

 スレッド間データ通信。

成果物

参照

メッセージ

 スレッド間でのデータ通信は「メッセージ」を介して行う。

チャンネル

 メッセージは「送信」と「受信」の2チャンネルにて行う。

use std::thread;
use std::sync::mpsc;
fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap();
    });
    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}
$ rustc main.rs
$ ./main
Got: hi
  • 送受信チャンネル生成: std::sync::mpsc::channel()
  • 値の送信: Sender<T>.send(値)
  • 値の受信:
    • 待機: Receiver.recv()
    • 順次: Receiver.try_recv()
    • 期間待機: Receiver.timeout(Duration)

 mainスレッドは新規スレッドのメッセージが送信されるまで待機する。

所有権の送信

use std::thread;
use std::sync::mpsc;
fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap();
        println!("val is {}", val);
    });
    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}
$ rustc main.rs
error[E0382]: use of moved value: `val`
  --> main.rs:12:31
   |
11 |         tx.send(val).unwrap();
   |                 --- value moved here
12 |         println!("val is {}", val);
   |                               ^^^ value used here after move
   |
   = note: move occurs because `val` has type `std::string::String`, which does not implement the `Copy` trait

 送信後は所有権がムーブされた後なので使えない。

複数の値を送信

use std::thread;
use std::sync::mpsc;
use std::time::Duration;
fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];
        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
    for received in rx {
        println!("Got: {}", received);
    }
}
$ rustc main.rs
$ ./main
Got: hi
Got: from
Got: the
Got: thread

Sender::clone()

use std::thread;
use std::sync::mpsc;
use std::time::Duration;
fn main() {
    let (tx, rx) = mpsc::channel();
    let tx1 = mpsc::Sender::clone(&tx);
    thread::spawn(move || {
        let vals = vec![
            String::from("1"),
            String::from("2"),
            String::from("3"),
            String::from("4"),
        ];
        for val in vals {
            tx1.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
    thread::spawn(move || {
        let vals = vec![
            String::from("A"),
            String::from("B"),
            String::from("C"),
            String::from("D"),
        ];
        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
    for received in rx {
        println!("Got: {}", received);
    }
}
$ ./main
Got: 1
Got: A
Got: 2
Got: B
Got: C
Got: 3
Got: D
Got: 4

 順序不定

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで