use*_*401 16 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();
Run Code Online (Sandbox Code Playgroud)
理想情况下,m.unlock_shared(); m.lock();可以用类似m.upgrade_to_exclusive();(或类似的东西boost::.upgrade_to_unique_lock())替换.
在一个类似的问题,但对于Boost的shared_mutex Dave S提及
在不释放共享锁的情况下,无法从共享锁转换为唯一锁,或共享锁转换为可升级锁.
我不确定这是否适用于std :: shared_mutex,尽管我怀疑它确实如此.
基于std :: atomic/condition_variable或GCC的事务内存,我会对合理的解决方法感到满意.
编辑:霍华德的回答解决了我的问题.他的提议N3427包含了实现互斥升级的机制的很好的描述.我仍然欢迎基于std :: atomic/condition_variable或GCC事务内存的解决方法.
How*_*ant 17
不,它不能.该功能被提议的名义委员会upgrade_mutex和upgrade_lock,但该委员会选择拒绝该提议的部分.目前还没有任何工作可以重新设置该功能.
编辑
在user3761401的问题中,为了回应"从这里开始"的编辑,我在upgrade_mutex/upgrade_lock这里创建了一个部分残缺的实现:
https://github.com/HowardHinnant/upgrade_mutex
随意使用它.它属于公共领域.它只是经过轻微测试,并没有N3427中描述的全部功能.具体而言,缺少以下功能:
unique_lock为a shared_timed_lock.shared_timed_lock为a unique_lock.upgrade_lock为a unique_lock.话虽这么说,我已经包含了这个功能upgrade_mutex,它可以在这个低级别以非常丑陋的方式访问(这些例子在main.cpp中).
可以使用N3427中提到的其他锁定转换.
shared_timed_lock到upgrade_lock.upgrade_lock为shared_timed_lock.upgrade_lock为unique_lock.unique_lock为upgrade_lock.它已全部投入使用namespace acme.把它放在你想要的任何名称空间中.
要求
编译器需要支持"rvalue-this"限定符和显式转换运算符.
免责声明
代码只是经过了轻微的测试.如果你发现错误,我会很感激拉取请求.
可以upgrade_mutex通过使用来优化std::atomic.在这方面没有做任何努力(这是一项困难且容易出错的任务,比现在花费的时间更多).