我根据 C++11 注释编写了一个非常简单的 Producer/Consumer,无法弄清楚为什么 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';
}
}
现在,如果我想在 Producer 或 Consumer 如果 sleep 有风险,我该如何引入一点节流?