目次

Rustの勉強[並行性 その2]

ぎじゅつ

はじめに

#

NO IMAGEThe Rust Programming Language 日本語版 - The Rust Programming Language 日本語版
を読んでいる

  • 久し振りにMacで勉強している
  • めちゃくちゃ眠い
  • 夕方に起きたら店が閉まる時間が近くてこれできなかった
    • 夜にもやっていていくれ

お勉強

#

NO IMAGEスレッドを使用してコードを同時に走らせる - The Rust Programming Language 日本語版

  • ここから
  • spawnjoinに認識のミスがないかだけ確認する

メモ

#
  • 普段はtokioみたいなcrateを使うって話があったがまあ勉強しておくのがよさそう
use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        for i in 1..10 {
            //       "やあ!立ち上げたスレッドから数字{}だよ!"
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        //       "やあ!メインスレッドから数字{}だよ!"
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}
hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
  • あ、必ずしもspawnしたスレッドからスタートするわけじゃないんだな
    • 記述順序的に先に動くのかと

thread::sleepを呼び出すと、少々の間、スレッドの実行を止め、違うスレッドを走らせることができます。

  • へぇ~
    • むちゃくちゃ重いときに使うんだろうか

Rustプログラムのメインスレッドが完了するときには、立ち上げられたすべてのスレッドは、その実行が完了したかどうかにかかわらず、停止されることに注意してください。
立ち上げたスレッドにはiが9になるまで出力するよう指示しているのに、メインスレッドが終了する前の5までしか到達していません。

  • あーたしかにね
  • だからjoin使うんだっけか

NO IMAGEスレッドを使用してコードを同時に走らせる - The Rust Programming Language 日本語版

  • やはり
use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

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

    handle.join().unwrap();
}
  • handleってなんだ

NO IMAGEspawn in std::thread - RustSpawns a new thread, returning a JoinHandle for it.

  • これか
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
    F: FnOnce() -> T + Send + 'static,
    T: Send + 'static,
  • おいおい、JoinHandle<T>って戻り値もともとあるじゃん
  • 先に紹介してくれ

JoinHandleは、そのjoinメソッドを呼び出したときにスレッドの終了を待つ所有された値です。

  • 書いてはあったが

  • handle.join().unwrap();を次の処理の前に置いたりすると、そこまで終了を待つらしい

  • なるほどなー

  • 前回読んだmoveクロージャを俯瞰して思ったけど、関数としと切り出すのもなーというのはここでクロージャにすれないいんだな

NO IMAGEメッセージ受け渡しを使ってスレッド間でデータを転送する - The Rust Programming Language 日本語版

Go言語のドキュメンテーションのスローガンにある考えです: 「メモリを共有することでやり取りするな; 代わりにやり取りすることでメモリを共有しろ」

Do not communicate by sharing memory; instead, share memory by communicating.

  • これか

まとめ

#
  • spawnjoinの使い方はシンプルなのでわかった
    • 平行して処理する単位としてスレッドという名称が存在している
    • そのスレッドを生成するのがspawn
    • そのままスレッド内で処理してしまうと終わるまえに終了してしまう可能性があるのでjoinを呼びだして終了待機のポイントを作っておく
  • 蛇足だけど寝むいときって本当に集中はできないな
  • 並行処理って実はあんまり使ったことなかったからゆっくりじっくりやるしかないかも

次はこれを光らせる

NO IMAGEメッセージ受け渡しを使ってスレッド間でデータを転送する - The Rust Programming Language 日本語版