我编写了一个非常简单的基于C ++ 11注释的生产者/消费者,并且无法弄清楚为什么unique_lock()在超出范围时不会释放锁。
struct Message{
Message(int x):data(x){cout<<"+";}
int data;
};
queue<Message*> g_queue;
condition_variable cv;
mutex m;
void consumer()
{
do {
unique_lock<mutex> lck {m};
cv.wait(lck, [&](){return !g_queue.empty();});
cout<<"Notified...";
auto& obj = g_queue.front();
std::cout<<obj->data;
g_queue.pop();
cout<<".";
lck.unlock(); -----(1)
} while(1);
}
void producer()
{
while(true){
unique_lock<mutex> lck {m};
Message msg{5};
cout<<"Queue size:"<<g_queue.size()<<'\n';
g_queue.push(&msg);
cv.notify_one();
lck.unlock(); -------(2)
cout<<"-"<<'\n';
this_thread::sleep_for(std::chrono::milliseconds{2000});
}
}
并将其用作: -
thread Q(&consumer);
thread P(&producer);
P.join();
Q.join();
输出结果为: -
+Queue size:0
-Notified...
5.+Queue size:0
-Notified...5
.+Queue size:0
-Notified...5
从技术上讲,是的,生产者需要告诉消费者我已做好准备,消费者需要让生产者知道发送更多数据。我不清楚使用什么,条件变量是这样做还是unique_lock这样做。
准确地说,为什么我需要(1)和(2)当范围可以释放锁
==编辑== 以下是经过编辑的代码,工作正常,
void consumer()
{
do {
unique_lock<mutex> lck {m};
cv.wait(lck, [&](){return !g_queue.empty();});
cout<<"Notified...";
auto& obj = g_queue.front();
std::cout<<obj->data;
g_queue.pop();
cout<<".";
} while(1);
}
Message msg{5};
void producer()
{
while(true){
unique_lock<mutex> lck {m};
cout<<"Queue size:"<<g_queue.size()<<'\n';
g_queue.push(&msg);
cv.notify_one();
cout<<"-"<<'\n';
}
}
现在,如果我希望在生产者或消费者中,如果睡眠有风险,我该如何引入一点油门?
答案 0 :(得分:0)
不确定这里还有一个问题,但是一种限制解决方案是允许队列在生产者中增长到最大大小。当队列达到此大小时,生成器将等待不同的条件变量。当队列低于特定大小时,消费者发出第二个条件变量的信号。 (后者的大小可能稍微小于给出一些滞后的最大值。)等待这个新条件变量的谓词是g_queue.size() >= max_size
。