云访客类似的网站,手机端网站动效类怎么做,1688货源网一件代发什么意思,小学门户网站建设方案先看几个问题#xff0c;第三个问题可以先看代码然后再理解
Q1#xff1a;临界区在哪
A1: 队列中元素在「生产者生产#xff08;push#xff09;」和「消费者消费#xff08;pop#xff09;」时就是临界区
Q2#xff1a;同步操作在哪
A2: 很显然#xff0c;队列只有…先看几个问题第三个问题可以先看代码然后再理解
Q1临界区在哪
A1: 队列中元素在「生产者生产push」和「消费者消费pop」时就是临界区
Q2同步操作在哪
A2: 很显然队列只有在存在元素的前提下消费者才能消费队列中元素满假设有容量线程时只有生产者是不能生产的因此
生产者队列满了就应该通知消费者消费消费者线程发现队列为空就需要通知生产者线程先生产物品
Q3为什么消费者在 cv.wait(lck) 的条件是 while 而不是 if
A3: cv.wait(lock) 本质上是阻塞的它会一直等待直到接收到 notify 或 notify_all 的通知。但是在某些情况下虽然没有收到通知但 cv.wait(lock) 可能会返回。这种情况被称为虚假唤醒spurious wakeup。
虚假唤醒是因为条件变量的实现方式以及底层操作系统和硬件的影响。条件变量的实现通常依赖于底层的线程库和操作系统它们可能在某些情况下引发虚假唤醒这是一种难以避免的情况。
因此为了编写健壮的多线程代码通常建议使用循环来检查条件就像在前面的示例中使用的 while (dataQueue.empty()) 一样。这样即使发生虚假唤醒线程也会再次检查条件确保只有在条件满足时才继续执行。
总之虽然 cv.wait(lock) 通常是阻塞的但在多线程环境中考虑到虚假唤醒是一种良好的编程实践以确保正确性和可靠性。
总结来说就是 cv.wait(lock)可能会在某些情况下如操作系统调度或硬件中断等自行返回。因此为了保险起见应该在一个循环中检查条件如示例中使用的 while (dataQueue.empty())以防止虚假唤醒导致的错误行为
完整代码如下
#include iostream
#include queue
#include thread
#include memory
#include condition_variableusing namespace std;std::mutex mtx; // 互斥锁实现线程之间的互斥操作
std::condition_variable cv; // 条件变量实现线程之间通信操作class Queue {public:void put(int val) {unique_lockstd::mutex lck(mtx);if (q.size() 10) {// 生产者队列满了就应该通知消费者消费// 生产者线程应该进入 #1 等待状态并且 #2 把 mtx 释放掉cv.wait(lck);}q.push(val);/*** brief 通知所有线程 notify_all()通知一个线程 notify_one()* 通知其他所有的线程我生产了一个物品你们赶紧地去消费* 其他线程得到了该通知就会从等待状态 阻塞状态 获取互斥锁之后才能继续执行*/cv.notify_all();cout 生产者 生产: val 号物品\n;}void get() {unique_lockstd::mutex lck(mtx);//!NOTE: 这里写成 while 是为了防止 cv.wait 被虚假唤醒while (q.empty()) {// 消费者线程发现队列为空就需要通知生产者线程先生产物品// #1 进入等待状态 #2 释放 mtxcv.wait(lck);}int val q.front();q.pop();// 通知其他所有的线程我消费了一个物品你们赶紧地去生产cv.notify_all();cout 消费者 消费: val 号物品\n;}private:queueint q;
};void producer(Queue *q) // 生产者线程
{for (int i 1; i 10; i) {q-put(i);std::this_thread::sleep_for(std::chrono::microseconds(100));}
}void consumer(Queue *q) // 消费者线程
{for (int i 1; i 10; i) {q-get();std::this_thread::sleep_for(std::chrono::microseconds(100));}
}int main() {Queue q;std::thread t1(producer, q);std::thread t2(consumer, q);t1.join();t2.join();return 0;
}参考
https://www.0xffffff.org/2016/02/11/38-c±concurrency/http://faq.0xffffff.org/question/2014/07/28/the-question-on-mutex-and-cond/
源码地址链接 C 面试总结 CPPGuide