use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc::{channel, Receiver, Sender};
fn main() {
let counter = Arc::new(Mutex::new(0));
let (tx, rx): (Sender<()>, Receiver<()>) = channel();
let mut handles = Vec::new();
for _ in 0..10 {
let counter_clone = Arc::clone(&counter);
let tx_clone = tx.clone();
let handle = thread::spawn(move || {
loop {
let mut num = counter_clone.lock().unwrap();
*num += 1;
println!("子线程增加counter到: {}", *num);
if *num >= 100 {
tx_clone.send(()).unwrap();
break;
}
}
});
handles.push(handle);
}
if let Ok(_) = rx.recv() {
for handle in handles {
handle.join().unwrap();
}
println!("所有线程已停止");
}
}
关键控制流部分详细解释:
- 共享计数器:
- 使用
Arc<Mutex<i32>>
来创建一个可在多线程间共享且线程安全的计数器counter
。Arc
(原子引用计数)允许在多个线程间共享数据,Mutex
(互斥锁)用于保护数据,确保同一时间只有一个线程可以访问和修改计数器。
- 通道创建:
- 使用
mpsc::channel()
创建一个通道(tx, rx)
。tx
(发送者)用于子线程向主线程发送通知,rx
(接收者)用于主线程接收通知。
- 子线程逻辑:
- 在每个子线程中,通过
counter_clone.lock().unwrap()
获取锁来修改计数器的值。
- 使用
if *num >= 100
判断计数器是否达到100,如果达到则通过tx_clone.send(()).unwrap()
向主线程发送通知,并通过break
跳出循环停止子线程工作。
- 主线程逻辑:
- 使用
if let Ok(_) = rx.recv()
等待接收子线程发送的通知。当接收到通知后,遍历所有子线程的handle
,通过handle.join().unwrap()
等待所有子线程结束,最后打印"所有线程已停止"。这样确保了主线程在所有子线程停止后才执行打印操作。