14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rustで並列処理する湯婆婆を実装してみる

Last updated at Posted at 2020-11-06

元ネタ

@NemesisさんのJavaで湯婆婆を実装してみるに便乗してみました。

のんびり書いてる間に先を越された。

Rustで湯婆婆を実装してみる

でもせっかくだから投稿しちゃう。

コード

use std::sync::{Arc, Mutex, Barrier};
use std::thread;
use rand::Rng;

fn main() {
    let mut handles = Vec::with_capacity(3);
    let name = Arc::new(Mutex::new(String::new()));
    let barrier = Arc::new(Barrier::new(3));

    handles.push(thread::spawn({
        let name = name.clone();
        let barrier = barrier.clone();
        move || {
            {
                let stdin = std::io::stdin();
                let mut locked = name.lock().unwrap();
                println!("湯婆婆A:契約書だよ。そこに名前を書きな。");
                let _ = stdin.read_line(&mut *locked);
            }
            barrier.wait();
        }
    }));

    handles.push(thread::spawn({
        let name = name.clone();
        let barrier = barrier.clone();
        move || {
            barrier.wait();
            let mut locked = name.lock().unwrap();
            println!("湯婆婆B:フン。{}というのかい。贅沢な名だねぇ。", locked.trim());
            let n = rand::thread_rng().gen_range(0, locked.trim().chars().count());
            *locked = locked.trim().chars().nth(n).unwrap().to_string();
        }
    }));

    handles.push(thread::spawn({
        let name = name.clone();
        let barrier = barrier.clone();
        move || {
            barrier.wait();
            println!("湯婆婆C:今からお前の名前は{0}だ。いいかい、{0}だよ。分かったら返事をするんだ、{0}!!", name.lock().unwrap().trim());
        }
    }));

    handles.into_iter().for_each(|h| { let _ = h.join(); });
}

ポイズン湯婆婆

空白のままにしますと、あるスレッドがMutexをロックしたまま終了しますので、湯婆婆Cはポイズンエラーが発生します。ポイズン湯婆婆

Screenshot from 2020-11-06 22-06-26.png

もちろん湯婆婆Bはクラッシュ湯婆婆してます。

連帯感

たまに湯婆婆Cがでしゃばります。
Screenshot from 2020-11-06 22-01-14.png

おわりに

Rustは並列処理を比較的気持ちよくかけます。

しかし、やっぱり並列処理の基本的な考えをおろそかにしていると、デバックしにくかったり、実行タイミングが管理しきれなくなったりします。

それでも、Rustは並列処理を書きやすいです。

メモリ競合を抑えるためのMutexやタイミングを合わせるためのbarrier、デバックに関してはstd::io::Errornewすれば手軽にデバック用のメッセージを飛ばせる(要件に合わせて自作Error型を作ったほうがいい気はするけど。。)。

Rustはいいですよぉ。とくにC++を学んだ方にはおすすめします。C++経験者であればすんなり馴染めることでしょう。

14
12
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?