-
Rust: Go와 비슷하게 멀티쓰레딩 짜기컴퓨터/Rust 2022. 8. 29. 14:37728x90반응형
my_map := make(map[string]string) var wg sync.WaitGroup wg.Add(len(my_map )) for key := range my_map { go func(key string) { defer wg.Done() stdout, _ := exec.Command(key, "some command").Output() lock.Lock() defer lock.Unlock() my_map[key] = "updating map value while iterating" // eg stdout }(key) }
어느 날 위와 같이 Go언어로 작성한 것을 Rust로 옮기려다가 배운 것이다.
위 Go언어으로 짠 걸 보면 우선 Map을 만들고 key마다 돌면서 thread를 spawn 하고 각 key를 업데이트한다.
Go에서는 쉽게 sync.WaitGroup과 lock을 이용해서 멀티쓰레드를 할 수 있었는데
Rust에서 짜려니 개념을 잘 몰랐다.
let mut my_map = HashMap::new(); ... for (key, value) in my_map.iter_mut() { // Should update map value, tried with crossbeam_utils:thread; thread::scope(|s| { s.spawn(|_| { let cmd = format!("some command {key}"); // will borrow key let cmd: Vec<&str> = cmd.as_str().split(" ").map(|s| s).collect(); let proc = Popen::create( &cmd, PopenConfig { stdout: Redirection::Pipe, stdin: Redirection::None, stderr: Redirection::None, ..Default::default() }, ); let mut proc = proc.expect("Failed to create process."); let (out, _) = proc.communicate(None).unwrap(); let stdout = out.unwrap(); *value = "I will update value with something new"; }); }) .unwrap(); }
처음에 위처럼 짰다가 각 key 마다 thread를 spawn은 하는데 다음 key로 iterate 할 때까지 thread가 join 된다는 것이었다.
또 Rust는 borrowing 기능도 있어 위처럼 하면 mutable borrowing 에러가 난다.
원하는 방식은 Go처럼 그냥 thread를 다 spawn 해놓고 map for문 끝나면 거의 동시에 다 같이 value를 업데이트하는 것이다.
Rust는 heavy OS 쓰레드 방식 (stack 갖고 있음), Go는 green 쓰레딩 모델이라고 한다.
수정한 방식은 애초에 thread::scope를 이용해서 새로운 영역을 만들고 안에서 쓰레드를 spawn하면
non 'static object도 borrow 할 수가 있다.
그리고 영역이 끝날 때는 모든 scoped thread들이 join 하기 때문에 이후에도 계속 변수를 사용할 수가 있다.
#![allow(unused)] fn main() { use std::thread; let mut a = vec![1, 2, 3]; let mut x = 0; thread::scope(|s| { s.spawn(|| { println!("hello from the first scoped thread"); // We can borrow `a` here. dbg!(&a); }); s.spawn(|| { println!("hello from the second scoped thread"); // We can even mutably borrow `x` here, // because no other threads are using it. x += a[0] + a[2]; }); println!("hello from the main thread"); }); // After the scope, we can modify and access our variables again: a.push(4); assert_eq!(x, a.len()); }
728x90'컴퓨터 > Rust' 카테고리의 다른 글
Rust: Generic Associated Types (GAT) (0) 2022.12.19 Rust: HashMap 값 for 문에서 update하기 (0) 2022.08.10 Windows: 저장된 WIFI 와이파이 비밀번호 보기 (0) 2022.08.10