c++ - std::shared_timed_mutex 上的共享锁可以升级为独占锁吗?

标签 c++ multithreading c++11 c++14

新的 std::shared_timed_mutex 允许两种类型的锁:共享锁和排他锁。

如果一个人持有共享锁,有没有办法将它原子交换(“升级”)为独占锁?换句话说,给定以下代码,我怎样才能避免非原子丢弃和重新锁定?

std::shared_timed_mutex m; //Guards a std::vector.
m.lock_shared();

//Read from vector. (Shared lock is sufficient.)
// ...

//Now we want to write to the vector. We need an exclusive lock.
m.unlock_shared();
                   //     <---- Problem here: non-atomic! 
m.lock(); 

//Write to vector.
// ...

m.unlock();

理想情况下,m.unlock_shared(); m.lock(); 可以替换为 m.upgrade_to_exclusive(); 之类的东西(或 boost::.upgrade_to_unique_lock() 之类的东西)。

In a similar question but for Boost's shared_mutex戴夫 S 提到

It is impossible to convert from a shared lock to a unique lock, or a shared lock to an upgradeable lock without releasing the shared lock first.

我不确定这是否适用于 std::shared_mutex,但我怀疑它确实如此。

我会对基于 std::atomic/condition_variable 或 GCC 事务内存的合理解决方法感到满意。

编辑:霍华德的回答解决了我的问题。他的proposal N3427包含对实现互斥升级的机制的很好的描述。我仍然欢迎基于 std::atomic/condition_variable 或 GCC 事务内存的变通方法。

最佳答案

不,它不能。该功能以 upgrade_mutexupgrade_lock 的名称向委员会提出,但委员会选择拒绝该部分提案。目前没有任何工作可以重新设置该功能。

编辑

为了响应 user3761401 的问题中的“从这里去哪里”编辑,我在这里创建了一个部分残缺的 upgrade_mutex/upgrade_lock 实现:

https://github.com/HowardHinnant/upgrade_mutex

请随意使用。它在公共(public)领域。它只是经过轻微测试,不具备N3427 中描述的全部功能。 .特别是缺少以下功能:

  • 无法将 unique_lock 转换为 shared_timed_lock
  • 不能尝试或定时将 shared_timed_lock 转换为 unique_lock
  • 不能尝试或定时将 upgrade_lock 转换为 unique_lock

话虽如此,我已经在 upgrade_mutex 中包含了这个功能,并且可以在这个低级别以非常丑陋的方式访问它(这样的例子在 main.cpp 中)。

N3427 中提到的其他锁转换可用。

  • shared_timed_lockupgrade_lock 的尝试和定时转换。
  • upgrade_lock 转换为 shared_timed_lock
  • 阻止从 upgrade_lockunique_lock 的转换。
  • unique_lock 转换为 upgrade_lock

已全部放入 namespace acme。把它放在你想要的任何命名空间中。

要求

编译器需要支持“rvalue-this”限定符和显式转换运算符。

免责声明

该代码仅经过轻微测试。如果您发现错误,我将不胜感激。

可以通过使用std::atomic来优化upgrade_mutex。在这方面没有做任何努力(这是一项困难且容易出错的任务,比我目前花费的时间更多)。

关于c++ - std::shared_timed_mutex 上的共享锁可以升级为独占锁吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24334735/

相关文章:

python - 使用 boost python 从 C++ 为 python 中的类成员变量赋值

c++ - 试图在 mysql 中添加 udf 给出错误 ERROR 1127 (HY000) : Can't find symbol in library

C++ Make Lower 函数

java - 多线程问题无法等待线程完成

c++ - 可以在主体中调用 C++ 中的委托(delegate)构造函数还是仅在初始化列表中调用?

c++ - C++ 中的 Pause()、Sleep() 和 Wait() 有什么区别?

c - C 中的多线程矩阵乘法

c# - 在 C# 中有效地管理线程

c++ - 通过部分模板特化扩展命名空间 std

c++ - 虽然 unique_ptr 保证在移动后存储 nullptr,但它仍然指向对象?