先理解核心场景:生产者-消费者模型
这段代码模拟的是生活中工厂生产商品,顾客消费商品的场景:
- 生产者线程:负责往仓库(队列)里放商品(数字)
- 消费者线程:负责从仓库里取商品(数字)
- 核心问题:要保证仓库不会被同时操作(比如生产和消费撞车),消费者不会去拿空仓库里的东西
逐部分拆解代码(零基础友好版)
1. 全局变量:公共资源
std::queue<int> q; // 仓库(队列),存数字(商品)
std::mutex mtx; // 仓库的锁,只有拿到锁才能动仓库
std::condition_variable cv; // 通知器:生产者喊消费者“有货了”
- 队列
q:像排队买奶茶,先放进去的数字先被拿出来(先进先出) - 锁
mtx:仓库门的钥匙,同一时间只有一个人能拿到钥匙开门 - 条件变量
cv:生产者喊“仓库有货了,快来取!”
2. 生产者函数:生产商品
void producer() {
// 生产9个数字(0-8)
for (int i = 0; i < 9; i++) {
{ // 这个大括号是“锁的作用范围”,出了括号自动解锁
// 上锁:拿到仓库钥匙,别人暂时不能动仓库
std::lock_guard<std::mutex> lock(mtx);
q.push(i); // 把数字i放进仓库
std::cout << "生产" << i << std::endl; // 打印生产信息
} // 解锁:用完钥匙,还回去
Sleep(1000); // 休息1秒(模拟生产需要时间)
cv.notify_one(); // 喊一声:有货了,通知消费者
}
}
通俗解释:
- 生产者每次生产一个数字,先拿钥匙打开仓库门(上锁),把数字放进去,然后还钥匙(解锁)
- 生产一个歇1秒(模拟真实生产耗时)
- 生产完喊一声,告诉消费者“有新货了”
3. 消费者函数:消费商品
void consumer() {
// 死循环:一直等着消费,直到消费到6就退出
while (1) {
// 上锁:拿仓库钥匙(unique_lock是可以临时解锁的锁,适合等通知)
std::unique_lock<std::mutex> lock(mtx);
// 等通知:如果仓库空,就放下钥匙等;仓库有货了,再拿钥匙继续
cv.wait(lock, []() {return !q.empty(); });
// 仓库有货了,开始消费
int v = q.front(); // 取仓库里第一个商品
q.pop(); // 把这个商品从仓库拿走
std::cout << "消费" << v << std::endl; // 打印消费信息
// 消费到6就停止(退出死循环)
if (v == 6) break;
}
}
通俗解释:
- 消费者一直等着,先拿钥匙,但如果仓库空了,就把钥匙放下,等着生产者喊“有货了”
- 等生产者喊了之后,再拿钥匙,从仓库里取第一个数字,拿走并打印
- 只要拿到数字6,就不消费了,直接走人
4. 主函数:启动程序
int main() {
// 创建两个线程:t1是生产者,t2是消费者
std::thread t1(producer);
std::thread t2(consumer);
// 等待线程结束:主线程等t1、t2都干完活,再结束程序
t1.join();
t2.join();
return 0;
}
通俗解释:
- 老板(main函数)招了两个员工:t1负责生产,t2负责消费
join():老板不先走,等两个员工都干完活,再关门下班
代码运行过程(零基础能懂的流程)
- 程序启动,同时启动生产者和消费者线程
- 生产者先生产0 → 歇1秒 → 喊消费者;消费者拿到0,消费0
- 生产者生产1 → 歇1秒 → 喊消费者;消费者拿到1,消费1
- 以此类推,直到生产者生产6,消费者消费6后,直接退出(不再消费)
- 生产者还会继续生产7、8,但消费者已经走了,这两个数字会留在仓库里
- 生产者生产完9个数字后也退出,程序结束
总结(核心要点)
- 线程:就是同时干两件事(生产和消费),像工厂里的两个工人;
- 锁(mutex):保护公共仓库,防止生产和消费同时操作,避免乱套;
- 条件变量(cv):解决“消费者白等”问题,生产者有货了才通知消费者,不用消费者一直傻等。

1735

被折叠的 条评论
为什么被折叠?



