关于unique_lock和lock_guard混用的疑问

slwj 2019-02-25 05:01:21
各位好,看下面代码遇到两个问题:

1)为何unique_lock和lock_guard混用?条件变量不是只能和unique_lock配合使用吗

2)为何两段代码都要用花括号括起来,是说明lk的作用域吗?如下:

// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready6 = true;
std::cout << "main() signals data ready for processing\n";
}



// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv6.wait(lk, []{return processed; });
}


多谢各位!

源程序如下:


#include <iostream>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <string>
#include <thread>
#include <atomic>

using namespace std;
std::mutex m;
std::condition_variable cv6;
std::string data;
bool ready6 = false;
bool processed = false;

static void worker_thread()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv6.wait(lk, []{return ready6; });

// after the wait, we own the lock.
std::cout << "Worker thread is processing data\n";
data += " after processing";

// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completed\n";

// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv6.notify_one();
}

int main()
{
std::thread worker(worker_thread);

data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready6 = true;
std::cout << "main() signals data ready for processing\n";
}
cv6.notify_one();

// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv6.wait(lk, []{return processed; });
}
std::cout << "Back in main(), data = " << data << '\n';

worker.join();

return 0;
}
...全文
751 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
slwj 2019-03-04
  • 打赏
  • 举报
回复
引用 2 楼 sdghchj 的回复:
lock_guard和unique_lock都是RAII机制下的锁,即依靠对象的创建和销毁也就是其生命周期来自动实现一些逻辑,而这两个对象就是在创建时自动加锁,在销毁时自动解锁。所以如果仅仅是依靠对象生命周期实现加解锁的话,两者是相同的,都可以用,因跟生命周期有关,所以有时会用花括号指定其生命周期。但lock_guard的功能仅限于此。unique_lock是对lock_guard的扩展,允许在生命周期内再调用lock和unlock来加解锁以切换锁的状态。 根据linux下条件变量的机制,condition_variable在wait成员函数内部会先调用参数unique_lock的unlock临时解锁,让出锁的拥有权(以让其它线程获得该锁使用权加锁,改变条件,解锁),然后自己等待notify信号,等到之后,再调用参数unique_lock的lock加锁,处理相关逻辑,最后unique_lock对象销毁时自动解锁。 也即是说condition_variable的wait函数内伪代码如下: condition_variable::wait(std::unique_lock<std::mutex>& lk){ lk.unlock(); waiting_signal(); lk.lock(); }
结贴了,谢谢大侠!
sdghchj 2019-02-26
  • 打赏
  • 举报
回复
lock_guard和unique_lock都是RAII机制下的锁,即依靠对象的创建和销毁也就是其生命周期来自动实现一些逻辑,而这两个对象就是在创建时自动加锁,在销毁时自动解锁。所以如果仅仅是依靠对象生命周期实现加解锁的话,两者是相同的,都可以用,因跟生命周期有关,所以有时会用花括号指定其生命周期。但lock_guard的功能仅限于此。unique_lock是对lock_guard的扩展,允许在生命周期内再调用lock和unlock来加解锁以切换锁的状态。 根据linux下条件变量的机制,condition_variable在wait成员函数内部会先调用参数unique_lock的unlock临时解锁,让出锁的拥有权(以让其它线程获得该锁使用权加锁,改变条件,解锁),然后自己等待notify信号,等到之后,再调用参数unique_lock的lock加锁,处理相关逻辑,最后unique_lock对象销毁时自动解锁。 也即是说condition_variable的wait函数内伪代码如下: condition_variable::wait(std::unique_lock<std::mutex>& lk){ lk.unlock(); waiting_signal(); lk.lock(); }
taodm 2019-02-25
  • 打赏
  • 举报
回复
对于mutex,它们区别很小啊。条件变量?你这里又木有。

64,281

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧