唯一的锁和条件变量 - 显式调用unlock

时间:2014-10-13 17:41:37

标签: c++ multithreading c++11 std

我找到了一个示例代码,演示了如何使用条件变量:

#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中调用的(在每次迭代中解锁都是隐式调用的,所以这样做明确没有意义)?

2 个答案:

答案 0 :(得分:2)

std :: unique_lock使用RAII模式。

这意味着它不需要在互斥锁上明确调用unlock。这提供了异常安全性,即在锁定互斥锁之后出现异常的情况下,在明确解锁之前,它会在超出范围时自动解锁。

答案 1 :(得分:-1)

这对我来说似乎有误导性。使用条件变量需要使用互斥锁进行锁定。此示例对多个共享变量(condqu)使用相同的互斥锁。

我认为,如果fun1fun2在多个主题上运行,它将无法正常运行。

下面会更清楚:

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