chore(advance): Add example for Condvar -> 'src/advance/concurrency-with-threads/sync1.md'

pull/1004/head
Jerry Wang 2 years ago
parent 8ddc818afe
commit 76fee5bb9f

@ -487,6 +487,109 @@ inner counter: 3
Mutex { data: true, poisoned: false, .. } Mutex { data: true, poisoned: false, .. }
``` ```
例子2`生产者消费者`模型
我们有一个生产者线程(铁匠),他生产(打造)一件装备后,通知消费者线程(玩家)消费(购买)
消费者线程(玩家)消费(购买)后,通知生产者线程(铁匠)继续生产(打造),直到生产者线程退出
```rust
use std::{
sync::{Arc, Condvar, Mutex},
thread,
};
fn main() {
// 条件变量,它可以让一个线程进入等待(锁),直至被其他线程唤醒
let cond = Arc::new(Condvar::new());
let cond_clone = cond.clone();
// 互斥锁和条件变量组合使用时,一般用于条件判断依据
let mutex_lock = Arc::new(Mutex::new(false));
let mutex_lock_clone = mutex_lock.clone();
let mut total_count = 10;
thread::spawn(move || loop {
// 这里利用作用域获取了锁(MutexGuard<T>)的值后直接让它释放
let mut lock = { *mutex_lock_clone.lock().unwrap() };
// 如果 lock == false 表示铁匠(生产者)还没有打造出装备,因此进入等待,等待铁匠(生产者)打造装备
while lock == false {
// 这里进入等待前一定要释放 lock否则你拿着锁进入等待其他线程就无法获得锁了
// 这就是为什么上面要用作用域释放 lock 的原因
lock = *cond_clone.wait(mutex_lock_clone.lock().unwrap()).unwrap(); // 进入等待
}
// 如果 lock == true 表示铁匠(生产者)已经打造出了一件装备,因此我们就可以购买(消费)了
println!("玩家(消费者),购买了一件装备");
// 这里用用作用域包起来的原因,也是为了释放 lock
// 因为如果你拿着锁去唤醒铁匠(生产者)线程,它也肯定无法获得锁
{
// 消费完后,把 lock 的值改成 false
*mutex_lock_clone.lock().unwrap() = false;
}
// 唤醒生产者线程(其实这里是唤醒一个等待中的线程,只不过此时只有一个线程在等待,就是我们的生产者线程)
cond_clone.notify_one();
});
while total_count > 0 {
// 这里利用作用域获取了锁(MutexGuard<T>)的值后直接让它释放
let mut lock = { *mutex_lock.lock().unwrap() };
// 如果 lock == true 表示已经打造了一件装备,因此暂停生产,等待玩家(消费者)购买(消费)
while lock == true {
// 这里进入等待前一定要释放 lock否则你拿着锁进入等待其他线程就无法获得锁了
// 这就是为什么上面要用作用域释放 lock 的原因
lock = *cond.wait(mutex_lock.lock().unwrap()).unwrap(); // 进入等待
}
// 否则如果 lock == false 表示还没有打造装备,因此需要打造一件装备
total_count -= 1;
println!(
"铁匠(生产者),打造了一件装备,剩余材料总数: {}",
total_count
);
// 这里用用作用域包起来的原因,也是为了释放 lock
// 因为如果你拿着锁去唤醒玩家(消费者)线程,它也肯定无法获得锁
{
// 打造完后,把 lock 的值改成 true
*mutex_lock.lock().unwrap() = true;
}
// 唤醒消费者线程(其实这里是唤醒一个等待中的线程,只不过此时只有一个线程在等待,就是我们的消费者线程)
cond.notify_one();
}
}
```
运行这段代码
```console
铁匠(生产者),打造了一件装备,剩余材料总数: 9
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 8
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 7
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 6
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 5
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 4
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 3
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 2
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 1
玩家(消费者),购买了一件装备
铁匠(生产者),打造了一件装备,剩余材料总数: 0
玩家(消费者),购买了一件装备
```
## 信号量 Semaphore ## 信号量 Semaphore
在多线程中,另一个重要的概念就是信号量,使用它可以让我们精准的控制当前正在运行的任务最大数量。想象一下,当一个新游戏刚开服时(有些较火的老游戏也会,比如`wow`),往往会控制游戏内玩家的同时在线数,一旦超过某个临界值,就开始进行排队进服。而在实际使用中,也有很多时候,我们需要通过信号量来控制最大并发数,防止服务器资源被撑爆。 在多线程中,另一个重要的概念就是信号量,使用它可以让我们精准的控制当前正在运行的任务最大数量。想象一下,当一个新游戏刚开服时(有些较火的老游戏也会,比如`wow`),往往会控制游戏内玩家的同时在线数,一旦超过某个临界值,就开始进行排队进服。而在实际使用中,也有很多时候,我们需要通过信号量来控制最大并发数,防止服务器资源被撑爆。

Loading…
Cancel
Save