Concurrency (Rust)

  • ๋™์‹œ์„ฑ: ํ”„๋กœ๊ทธ๋žจ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ผ๋ถ€๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ.
  • ๋ณ‘๋ ฌ์„ฑ: ํ”„๋กœ๊ทธ๋žจ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ผ๋ถ€๋ฅผ ๊ฐ™์€ ์‹œ์ ์— ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ.

Thread

  • ๋งŽ์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๊ฐ€ ์ž์ฒด์ ์œผ๋กœ ํŠน๋ณ„ํ•œ ์Šค๋ ˆ๋“œ ๊ตฌํ˜„์„ ์ œ๊ณตํ•œ๋‹ค:
    • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ๊ทธ๋ฆฐ ์Šค๋ ˆ๋“œ(green thread)๋ผ๊ณ ๋„ ํ•˜๋ฉฐ, ์„œ๋กœ ๋‹ค๋ฅธ ์ˆ˜์˜ OS ์Šค๋ ˆ๋“œ๋กœ ์‹คํ–‰๋œ๋‹ค.
    • ๊ทธ๋ฆฐ ์Šค๋ ˆ๋“œ ๋ชจ๋ธ์„ M:N ๋ชจ๋ธ์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค: N๊ฐœ์˜ OS ์Šค๋ ˆ๋“œ ๋‹น M๊ฐœ์˜ ๊ทธ๋ฆฐ ์Šค๋ ˆ๋“œ๊ฐ€ ํ• ๋‹น๋œ๋‹ค.
  • ๋Ÿฌ์ŠคํŠธ๋Š” ์ €์ˆ˜์ค€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ด๋ฏ€๋กœ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ 1:1 ์Šค๋ ˆ๋”ฉ๋งŒ ์ œ๊ณตํ•œ๋‹ค.
  • thread::spawn ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค:
    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!
    
  • ์•„์ง ์Šคํฐ๋œ ์Šค๋ ˆ๋“œ์˜ ์ž‘์—…์ด ๋๋‚˜์ง€ ์•Š์•˜๋Š”๋ฐ๋„ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ์ž‘์—…์ด ๋๋‚˜๋Š” ๋ฐ”๋žŒ์— ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋˜์–ด ๋ฒ„๋ ธ๋‹ค.
  • thread::spawn ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” JoinHandle์˜ join ๋ฉ”์„œ๋“œ๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค:
    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();
    }
    
  • ์Šค๋ ˆ๋“œ ํด๋กœ์ € ์•ˆ์—์„œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์˜ค๋„ˆ์‹ญ์„ ์ด๋™์‹œ์ผœ์•ผ ํ•œ๋‹ค:
    • ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์Šค๋ ˆ๋“œ์—์„œ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋“œ๋กญ๋˜๋Š” ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค:
      use std::thread;
      
      fn main() {
          let v = vec![1, 2, 3];
      
          let handle = thread::spawn(|| {
              println!("Here's a vector: {:?}", v);
          });
      
          drop(v); // oh no!
      
          handle.join().unwrap();
      }
      
    • ํด๋กœ์ € ์•ž์— move ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ด๋ฉด ํด๋กœ์ €๊ฐ€ ์˜ค๋„ˆ์‹ญ์„ ๊ฐ–๊ฒŒ ๋œ๋‹ค:
      use std::thread;
      
      fn main() {
          let v = vec![1, 2, 3];
      
          let handle = thread::spawn(move || {
              println!("Here's a vector: {:?}", v);
          });
      
          handle.join().unwrap();
      }
      
      • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํด๋กœ์ €๊ฐ€ v์— ๋Œ€ํ•œ ์˜ค๋„ˆ์‹ญ์„ ๊ฐ–๊ณ  ์žˆ์œผ๋ฏ€๋กœ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ v๋ฅผ ๋“œ๋กญํ•  ์ˆ˜ ์—†๋‹ค.
      • ๋Ÿฌ์ŠคํŠธ์˜ ์˜ค๋„ˆ์‹ญ ๊ทœ์น™์ด ๋˜ ์šฐ๋ฆฌ๋ฅผ ๊ตฌํ–ˆ๋‹ค.

Async

  • ์Šค๋ ˆ๋“œ๋Š” ๋‹จ์ˆœํ•˜์ง€๋งŒ, ๋™๊ธฐํ™”๊ฐ€ ์–ด๋ ต๊ณ  ์„ฑ๋Šฅ ์˜ค๋ฒ„ํ—ค๋“œ๋„ ํฌ๋‹ค. ๋น„๋™๊ธฐ๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ž‘๋‹ค.
  • ๋น„๋™๊ธฐ๊ฐ€ ์Šค๋ ˆ๋“œ๋ณด๋‹ค ํ•ญ์ƒ ๋” ๋‚˜์€ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๊ตณ์ด ๋น„๋™๊ธฐ์˜ ์„ฑ๋Šฅ์ด ํ•„์š”ํ•œ๊ฒŒ ์•„๋‹ˆ๋ฉด ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ๋” ์‰ฝ๋‹ค.
  • ๋Ÿฌ์ŠคํŠธ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๊ธฐ๋ณธ์ ์ธ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋„๊ตฌ๋งŒ ์ œ๊ณตํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค:
    • futures: ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜์™€ ํŠธ๋ ˆ์ž‡๋“ค์„ ์ œ๊ณตํ•œ๋‹ค.
    • tokio or async-std: ๋น„๋™๊ธฐ ๋Ÿฐํƒ€์ž„์„ ์ œ๊ณตํ•œ๋‹ค.
  • async๋Š” ์ฝ”๋“œ ๋ธ”๋ก์„ Future ํŠธ๋ ˆ์ž‡์„ ๊ตฌํ˜„ํ•˜๋Š” ์ƒํƒœ ๋จธ์‹ ์œผ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค:
    async fn learn_and_sing() {
        // ๋…ธ๋ž˜๋ฅผ ๋ถ€๋ฅด๊ธฐ ์ „์— ๊ทธ ๋…ธ๋ž˜๋ฅผ ๋ฐฐ์šธ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
        // ์—ฌ๊ธฐ์„œ `block_on` ๋Œ€์‹  `.await`์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์Šค๋ ˆ๋“œ ๋ธ”๋กœํ‚น์„ ๋ฐฉ์ง€ํ•˜๊ณ ,
        // ๊ฐ™์€ ์‹œ์ ์— `dance`๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. `.await`๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•˜๋Š” ๋Œ€์‹ 
        // future๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
        let song = learn_song().await;
        sing_song(song).await;
    }
    
    async fn async_main() {
        let f1 = learn_and_sing();
        let f2 = dance();
    
        // `join!`์€ `.await`์™€ ๋น„์Šทํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ futures๋ฅผ ๋™์‹œ์— ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
        // ๋งŒ์•ฝ `learn_and_sing`๊ฐ€ ์ž ์‹œ ๋ธ”๋กœํ‚น๋˜๋ฉด, `dance`๊ฐ€ ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ ์œ ํ•  ๊ฒƒ์ด๋‹ค.
        // ๋งŒ์•ฝ `dance`๊ฐ€ ๋ธ”๋กœํ‚น๋˜๋ฉด, `learn_and_sing`์ด ๋‹ค์‹œ ์Šค๋ ˆ๋“œ๋ฅผ ์ ์œ ํ•œ๋‹ค.
        // ๋งŒ์•ฝ ๋‘˜ ๋‹ค ๋ธ”๋กœํ‚น๋˜๋ฉด `async_main`์ด ๋ธ”๋กœํ‚น๋˜๊ณ , ์‹คํ–‰์ž์—๊ฒŒ ์Šค๋ ˆ๋“œ๋ฅผ ์–‘๋ณดํ•  ๊ฒƒ์ด๋‹ค.
        // `let (book, music) = futures::join!(get_book, get_music);` ์ฒ˜๋Ÿผ ํŽ˜์–ด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
        futures::join!(f1, f2);
    }
    
    fn main() {
        // `block_on`์€ future๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•œ๋‹ค.
        block_on(async_main());
    }
    

Future

  • Future ํŠธ๋ ˆ์ž‡์€ ๋Ÿฌ์ŠคํŠธ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ.
  • ๋Œ€๋žต ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ๋‹ค:
    trait SimpleFuture {
        type Output;
        fn poll(&mut self, wake: fn()) -> Poll<Self::Output>;
    }
    
    enum Poll<T> {
        Ready(T),
        Pending,
    }
    
    • poll: future๊ฐ€ ์™„๋ฃŒ๋์œผ๋ฉด Poll::Ready(result)๋ฅผ, ์•„๋‹ˆ๋ฉด Poll::Pending์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • Poll::Pending ๋ฐ˜ํ™˜ ํ›„ future๊ฐ€ ๋” ์ง„ํ–‰ํ•  ์ค€๋น„๊ฐ€ ๋˜๋ฉด wake ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
    • wake ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์‹คํ–‰์ž๊ฐ€ ๋‹ค์‹œ poll์„ ํ˜ธ์ถœํ•จ์œผ๋กœ์จ future๋ฅผ ๋” ์ง„ํ–‰์‹œํ‚จ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€์˜ ์ฐจ์ด

  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” async-first ์–ธ์–ด๋‹ค.
  • ๋‘ ๊ฐ€์ง€ ๋ฉด์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ promise์™€ ๋Ÿฌ์ŠคํŠธ์˜ futures๋Š” ๋‹ค๋ฅด๋‹ค:
    1. promise๋Š” ์ƒ์„ฑ ์ฆ‰์‹œ ์Šค์ผ€์ค„๋œ๋‹ค. ๋ฐ˜๋ฉด, futures๋Š” await๋์„ ๋•Œ๋งŒ ์Šค์ผ€์ค„๋œ๋‹ค.
    2. ๋ชจ๋“  promies๋Š” fallibleํ•˜๋‹ค. ๋ฐ˜๋ฉด, futures๋Š” infallibleํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

์ด ๋ฌธ์„œ๋ฅผ ์ธ์šฉํ•œ ๋ฌธ์„œ