use std::sync::{Arc, Condvar, Mutex};
use std::thread;
fn main() {
let shared_data = Arc::new((Mutex::new(false), Condvar::new()));
let shared_data_clone = shared_data.clone();
// 线程1,用于检查条件并唤醒线程2
let thread1 = thread::spawn(move || {
let (lock, cvar) = &*shared_data_clone;
let mut data = lock.lock().unwrap();
*data = true;
println!("线程1设置条件为true");
// 唤醒所有等待的线程
cvar.notify_all();
});
// 线程2,等待条件满足
let thread2 = thread::spawn(move || {
let (lock, cvar) = &*shared_data;
let mut data = lock.lock().unwrap();
while!*data {
println!("线程2等待条件...");
data = cvar.wait(data).unwrap();
}
println!("线程2条件满足,继续执行");
});
thread1.join().unwrap();
thread2.join().unwrap();
}
代码解释
- 同步原语定义:
Arc
(原子引用计数)用于在多个线程间共享数据。这里共享的是一个元组,包含一个Mutex
和一个Condvar
。
Mutex
(互斥锁)用于保护共享数据,确保同一时间只有一个线程可以访问。
Condvar
(条件变量)用于线程的停放和唤醒。
- 线程1:
- 获取
Mutex
的锁,并将共享数据设置为true
。
- 调用
Condvar
的notify_all
方法,唤醒所有等待在这个条件变量上的线程。
- 线程2:
- 获取
Mutex
的锁,并通过while
循环检查共享数据。
- 如果共享数据为
false
,则调用Condvar
的wait
方法,释放Mutex
锁并停放线程。当被唤醒时,wait
方法重新获取Mutex
锁并返回。
- 主函数:
- 创建并启动两个线程
thread1
和thread2
。
- 调用
join
方法等待两个线程执行完毕,确保主线程不会提前退出。
避免死锁的措施
- 合理的锁获取顺序:在这个示例中,两个线程获取锁的顺序是一致的,都是先获取
Mutex
锁。如果多个线程需要获取多个锁,确保所有线程以相同的顺序获取锁,可以避免死锁。
- 条件变量的正确使用:
Condvar
的wait
方法在等待时会释放Mutex
锁,避免了等待过程中一直持有锁导致其他线程无法获取锁的情况,从而防止死锁。同时,notify_all
方法确保等待的线程能够被唤醒,继续执行。