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

时间:2014-06-20 19:57:10

标签: 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 Dave S提及

  

在不释放共享锁的情况下,无法从共享锁转换为唯一锁,或将共享锁转换为可升级锁。

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

我很乐意基于std :: atomic / condition_variable或GCC的事务内存进行合理的解决。

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

1 个答案:

答案 0 :(得分:15)

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

修改

在回复用户3761401的问题中的“从何处开始”编辑时,我在这里创建了一个部分残缺的upgrade_mutex/upgrade_lock实现:

https://github.com/HowardHinnant/upgrade_mutex

随意使用它。它属于公共领域。它只是经过轻微测试,并且没有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_lock转换为unique_lock
  • unique_lock转换为upgrade_lock

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

要求

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

免责声明

代码只是经过了轻微的测试。如果你发现错误,我会很感激拉取请求。

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