rust 并发

2018-08-12  本文已影响57人  xiongzenghui

1、启动子线程

use std::thread;

fn main() {
  // 启动子线程
  thread::spawn(|| {
    println!("Hello from a thread!");
  });

  // 死循环卡住主线程,否则主线程挂掉,上面的子线程也跟着挂掉
  // 也就无法看到子线程的输出
  loop{
  }
}
➜  main make
rustc main.rs
./main
Hello from a thread!
^Cmake: *** [all] Interrupt: 2

➜  main

2、线程异常

use std::thread;

fn main()
{
  let result = thread::spawn(move || {
    panic!("oops!");
  }).join();

 assert!(result.is_err());
}

3、同步等待子线程执行完毕

use std::thread;

fn main() {
  // 启动子线程
  let handle = thread::spawn(|| {
    println!("Hello from a thread!");
    return 99
  });

  let ret = handle.join().unwrap();
  println!("ret = {:?}", ret);
}
➜  main make
rustc main.rs
./main
Hello from a thread!
ret = 99
➜  main

4、子线程访问外部数据

use std::thread;

fn main() 
{
  let data = vec![1u32, 2, 3];

  let handle = thread::spawn(move || {
    println!("data = {:?}", data);
  });

  handle.join().unwrap();
}
➜  main make
rustc main.rs
./main
data = [1, 2, 3]
➜  main

5、共享可变数据

1. rust不允许线程修改外部的可变数据

use std::thread;

fn main() 
{
  // 可变绑定的数据
  let mut data = vec![1u32, 2, 3];

  // 启动3个线程,修改外部的可变数据
  for i in 0..3 {
    thread::spawn(move || {
      data[i] += 1; // 修改外的可变数据
    });
  }

  // 卡住主线程
  loop{}
}

编译报错

➜  main make
rustc main.rs
error[E0382]: capture of moved value: `data`
  --> main.rs:11:7
   |
10 |     thread::spawn(move || {
   |                   ------- value moved (into closure) here
11 |       data[i] += 1; // 修改外的可变数据
   |       ^^^^ value captured here after move
   |
   = note: move occurs because `data` has type `std::vec::Vec<u32>`, which does not implement the `Copy` trait

error: aborting due to previous error

make: *** [all] Error 101
➜  main

2. 只有实现Send接口的数据,才能够在线程间转移所有权

use std::sync::{Arc, Mutex};
use std::thread;

fn main() 
{
  // Arc -> Mutex -> Vec
  // Arc 丝线了 Send 接口,所以可以被其他子线程转移所有权
  let data = Arc::new(Mutex::new(vec![1u32, 2, 3]));

  // 启动3个线程,修改外部的可变数据
  for i in 0..3 {
    // 先拷贝一份
    let data = data.clone();

    // 子线程修改外的可变数据
    thread::spawn(move || {
      // 进入临界区加锁
      let mut data = data.lock().unwrap();

      // 修改临界区的数据
      data[i] += 1; 
    });
  }

  // 等待线程执行完毕,打印被修改的data数据
  thread::sleep_ms(50);
  println!("data = {:?}", data); 

  // 卡住主线程
  loop{}
}
➜  main make
rustc main.rs
./main
data = Mutex { data: [2, 3, 4] }
^Cmake: *** [all] Interrupt: 2

➜  main

6、使用【通道】同步多个线程

use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc;

fn main() {
  // 在多个线程之间使用的临界数据
  let data = Arc::new(Mutex::new(0u32));
  println!("{:?}", data);
  
  // 对多线程同步的通道
  let (tx, rx) = mpsc::channel(); 

  // 启动10个子线程修改临界区数据
  for _ in 0..10 {
    let (data, tx) = (data.clone(), tx.clone());

    thread::spawn(move || {
      // 加锁
      let mut data = data.lock().unwrap();
      // 修改临界区数据
      *data += 1;
      // 解锁 => 给通道发送消息,解除阻塞,执行下一个任务
      tx.send(());
      println!("data => {:?}", *data);
    });
  }

  // 控制10个子线程按照顺序依次执行
  for _ in 0..10 {
    rx.recv();
  }

  println!("{:?}", data);
}

7、向通道中发送数据

use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc;

fn main() {
  // 在多个线程之间使用的临界数据
  let data = Arc::new(Mutex::new(0u32));
  println!("{:?}", data);
  
  // 对多线程同步的通道
  let (tx, rx) = mpsc::channel(); 

  // 启动10个子线程修改临界区数据
  for _ in 0..10 {
    let tx = tx.clone();

    thread::spawn(move || {
      let answer = 42u32;
      tx.send(answer); // 向通道发送数据
    });
  }

  // 控制10个子线程按照顺序依次执行
  for _ in 0..10 {
    println!("{:?}", rx.recv().ok().expect("Could not receive answer")); // 从通道读取数据
  }
}
➜  main make
rustc main.rs
./main
Mutex { data: 0 }
42
42
42
42
42
42
42
42
42
42
➜  main
上一篇下一篇

猜你喜欢

热点阅读