std::condition_variable 是不是真的在阻塞之前解锁了给定的 unique_lock 对象?

Posted

技术标签:

【中文标题】std::condition_variable 是不是真的在阻塞之前解锁了给定的 unique_lock 对象?【英文标题】:Does std::condition_variable really unlock the given unique_lock object before blocking?std::condition_variable 是否真的在阻塞之前解锁了给定的 unique_lock 对象? 【发布时间】:2020-10-20 19:44:14 【问题描述】:

正如参考所说:1) Atomically unlocks lock, blocks the current executing thread, and...

我有以下代码:

#include <iostream>
#include <thread>
#include <condition_variable>

std::mutex mutex_;
std::condition_variable condVar;
std::unique_lock<std::mutex> lck(mutex_); //purposely global to check return of owns_lock() in main

void waitingForWork()

    std::cout << "Before wait, lck.owns_lock() = " << lck.owns_lock() << '\n';

    condVar.wait(lck);

    std::cout << "After wait, lck.owns_lock() = " << lck.owns_lock() << '\n';


int main()

  std::thread t1(waitingForWork);

  std::this_thread::sleep_for(std::chrono::seconds(10));

  std::cout << "In main, lck.owns_lock() = " << lck.owns_lock() << '\n';
  condVar.notify_one();

  t1.join();
  return 0;

编译使用:g++ with c++17 on ubuntu

输出:

Before wait, lck.owns_lock() = 1
In main, lck.owns_lock() = 1
After wait, lck.owns_lock() = 1

但根据参考,我希望互斥锁在等待时解锁,即:

In main, lck.owns_lock() = 0

谁能告诉我为什么会这样?

【问题讨论】:

【参考方案1】:

您必须进一步阅读:

解锁后,无论出于何种原因,都会重新获取锁定并等待退出。如果此函数因异常退出,也会重新获取锁。

因此始终保证在退出等待时重新获取锁。

【讨论】:

但是我问,为什么通过程序没有观察到相同的情况?输出与参考文档不一致。 main 中的 cout 在退出等待之前执行。 您的代码中实际上存在数据竞争。您正在从两个线程访问lck,但std::unique_lock 不是为此而设计的。很容易检查mutex_ 是否已解锁:尝试在sleep_for 之后立即获取main 中的互斥锁。

以上是关于std::condition_variable 是不是真的在阻塞之前解锁了给定的 unique_lock 对象?的主要内容,如果未能解决你的问题,请参考以下文章

在等待通知 std::condition_variable 期间执行“等待回调”

std::atomic 和 std::condition_variable 等待、notify_* 方法之间的区别

在等待std :: condition_variable时如何处理系统时钟更改?

如何正确使用 std::condition_variable?

关于std::thread以及std::condition_variable的一些细节备忘

std::condition_variable::notify_all() - 我需要一个例子