Rust②食事する哲学者
下記の題材でソースコードを読み解いていく。
https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/dining-philosophers.html
プロジェクトの開始-cargoを使用すること。
structで構造体を定義して
implで機能を定義する。Philosopherオブジェクトに引数の値を突っ込むこと
mainが動作を規定する
哲学者が一緒に食事するようにしたい場合
平行性の実装
これでマルチスレッドが実装できたらしい。すごいね。
古典的な並行処理問題の対応
これもうわかんねえな。
https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/dining-philosophers.html
◆事前準備
プロジェクトの開始-cargoを使用すること。
$ cd ~/projects
$ cargo new dining_philosophers --bin
$ cd dining_philosophers
簡単な構造struct Philosopher { name: String, } impl Philosopher { fn new(name: &str) -> Philosopher { Philosopher { name: name.to_string(), } } } fn main() { let p1 = Philosopher::new("Judith Butler"); let p2 = Philosopher::new("Gilles Deleuze"); let p3 = Philosopher::new("Karl Marx"); let p4 = Philosopher::new("Emma Goldman"); let p5 = Philosopher::new("Michel Foucault"); }解説
structで構造体を定義して
implで機能を定義する。Philosopherオブジェクトに引数の値を突っ込むこと
mainが動作を規定する
哲学者が一緒に食事するようにしたい場合
use std::thread; use std::time::Duration; struct Philosopher { name: String, } impl Philosopher { fn new(name: &str) -> Philosopher { Philosopher { name: name.to_string(), } } fn eat(&self) { println!("{} is eating.", self.name); thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } } fn main() { let philosophers = vec![ Philosopher::new("Judith Butler"), Philosopher::new("Gilles Deleuze"), Philosopher::new("Karl Marx"), Philosopher::new("Emma Goldman"), Philosopher::new("Michel Foucault"), ]; for p in &philosophers { p.eat(); } }ライブラリが追加されること
use std::thread; use std::time::Duration;
fn eat(&self) { println!("{} is eating.", self.name); thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); }この期間を待つことの実装ができた。
平行性の実装
let handles: Vec<_> = philosophers.into_iter().map(|p| { thread::spawn(move || { p.eat(); }) }).collect(); for h in handles { h.join().unwrap(); }解説
これでマルチスレッドが実装できたらしい。すごいね。
古典的な並行処理問題の対応
use std::thread; use std::time::Duration; use std::sync::{Mutex, Arc}; struct Philosopher { name: String, left: usize, right: usize, } impl Philosopher { fn new(name: &str, left: usize, right: usize) -> Philosopher { Philosopher { name: name.to_string(), left: left, right: right, } } fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); thread::sleep(Duration::from_millis(150)); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } } struct Table { forks: Vec<Mutex<()>>, } fn main() { let table = Arc::new(Table { forks: vec![ Mutex::new(()), Mutex::new(()), Mutex::new(()), Mutex::new(()), Mutex::new(()), ]}); let philosophers = vec![ Philosopher::new("Judith Butler", 0, 1), Philosopher::new("Gilles Deleuze", 1, 2), Philosopher::new("Karl Marx", 2, 3), Philosopher::new("Emma Goldman", 3, 4), Philosopher::new("Michel Foucault", 0, 4), ]; let handles: Vec<_> = philosophers.into_iter().map(|p| { let table = table.clone(); thread::spawn(move || { p.eat(&table); }) }).collect(); for h in handles { h.join().unwrap(); } }解説
これもうわかんねえな。