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