文章目录
在并发控制的面试里有个很喜欢考的点:如何控制两个并发线程交替打印1和2。
实现的方式有很多,今天我们先用上篇提到的condvar试试。
思路是利用条件变量来控制两个线程:
- 线程1:当且仅当条件为false时开始打印1,并修改条件为true, 通知等待的另一个线程打印2,否则while阻塞等待
- 线程2:条件为false时阻塞等待notify,直到条件为true,然后重置条件为false,并打印2
代码及注释如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| use std::sync::{Arc, Condvar, Mutex}; use std::thread;
fn main() { let pair = Arc::new((Mutex::new(false), Condvar::new())); let cnt = 3; let pair2 = pair.clone();
let t1 = thread::spawn(move || { let &(ref lock, ref cvar) = &*pair2; for _ in 0..cnt { while let Ok(mut v) = lock.lock() { if !*v { print!("1 "); *v = true; cvar.notify_one(); break; } else { drop(v); } } } }); let t2 = thread::spawn(move || { for _ in 0..cnt { let &(ref lock, ref cvar) = &*pair; let mut v = lock.lock().unwrap(); while !*v { v = cvar.wait(v).unwrap(); } *v = false;
print!("2 "); } }); t1.join().unwrap(); t2.join().unwrap(); }
|
运行结果可以实现打印 1 2 1 2 1 2
不过线程1用遍历阻塞其实还是消耗了不少cpu时间,恢复注释[1]的打印可以看出,又多次waitting输出
可以加一点等待 sleep 让出cpu占用,如注释[2]来减少频繁对锁的抢占。
其实这个题目用semaphore实现也很有意思,下一篇我们聊semaphore时再来看。
如有疑问,请文末留言交流或邮件:newbvirgil@gmail.com
本文链接 : https://newbmiao.github.io/2023/11/23/rust-sync-condvar-2.html