我找到了一个示例代码,演示了如何使用条件变量:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <deque>
using namespace std;
deque<int> qu;
mutex mu;
condition_variable cond;
void fun1()
{
int count = 100;
while (count > 0)
{
unique_lock<mutex> locker(mu);
qu.push_front(count);
locker.unlock(); // explicit unlock 1
cond.notify_one();
--count;
}
}
void fun2()
{
int data = 0;
while(data != 1)
{
unique_lock<mutex> locker(mu);
cond.wait(locker, [](){ return !(qu.empty()); });
data = qu.back();
qu.pop_back();
locker.unlock(); // explicit unlock 2
cout<<"data: "<<data<<endl;
}
}
int main()
{
thread t1(fun1);
thread t2(fun2);
t1.join();
t2.join();
system("pause");
return 0;
}
我认为没有必要明确地调用解锁。但是在fun1之前调用它可能会增加性能,对吗?为什么解锁是在fun2中调用的(在每次迭代中解锁都是隐式调用的,所以这样做明确没有意义)?
答案 0 :(得分:2)
std :: unique_lock使用RAII模式。
这意味着它不需要在互斥锁上明确调用unlock。这提供了异常安全性,即在锁定互斥锁之后出现异常的情况下,在明确解锁之前,它会在超出范围时自动解锁。
答案 1 :(得分:-1)
这对我来说似乎有误导性。使用条件变量需要使用互斥锁进行锁定。此示例对多个共享变量(cond
和qu
)使用相同的互斥锁。
我认为,如果fun1
或fun2
在多个主题上运行,它将无法正常运行。
下面会更清楚:
mutex mu;
mutex mu_for_cv;
condition_variable cond;
void fun1()
{
int count = 100;
while (count > 0)
{
unique_lock<mutex> locker(mu);
qu.push_front(count);
{
unique_lock<mutex> locker(mu_for_cv);
cond.notify_one();
}
--count;
}
}
void fun2()
{
int data = 0;
while(data != 1)
{
{
unique_lock<mutex> locker(mu_for_cv);
cond.wait(locker, [](){ return !(qu.empty()); });
}
unique_lock<mutex> locker(mu);
if (!qu.empty())
{
data = qu.back();
qu.pop_back();
cout<<"data: "<<data<<endl;
}
}
}
此外,最好在fun2
中检查队列是否为空以防御spurious wakeups。