scoped_lock可以在读模式下锁定shared_mutex吗?

Kai*_*zke 15 c++ deadlock scoped-lock

C++ 17引入了std::shared_mutexstd::scoped_lock.我现在的问题是scoped_lock,当它作为参数传递而不是在共享(读取器)模式下时,它将始终以独占(写入)模式锁定共享互斥锁.在我的应用程序中,我需要dst使用来自对象的数据更新对象src.我想锁定src共享和dst独占.不幸的是,如果同时调用另一个带有srcdst切换的更新方法,则可能会出现死锁.所以我想使用花哨的死锁避免机制std::scoped_lock.

我可以使用scoped_lock锁定srcdst独占模式,但不必要的严格锁具有其他地方的性能退缩.然而,现在看来,这是可能的包裹srcshared_mutex进入std::shared_lock和使用,用scoped_lock:当scoped_lock其锁定在行动电话try_lock()shared_lock,以后将实际调用try_shared_lock()srcshared_mutex,而这正是我需要的.

所以我的代码看起来很简单:

struct data {
    mutable std::shared_mutex mutex;
    // actual data follows
};

void update(const data& src, data& dst)
{
    std::shared_lock slock(src.mutex, std::defer_lock);
    std::scoped_lock lockall(slock, dst.mutex);
    // now can safely update dst with src???
}
Run Code Online (Sandbox Code Playgroud)

在另一个(死锁避免)锁定防护装置中使用这样的(共享)锁定防护装置是否安全?

Mel*_*ter 5

正如阅读过C ++标准库的实现代码的各种注释者所指出的那样:是的,将a std::shared_mutex内的换行符std::shared_lock()用作to的参数之一std::scoped_lock()是安全的。

基本上,a std::shared_lock将所有呼叫转移lock()lock_shared()互斥锁上。

std::shared_lock::lock -----------> mutex()->lock_shared(). // same for try_lock etc..
Run Code Online (Sandbox Code Playgroud)

另一种可能的解决方案

std::shared_lock lk1(src.mutex, std::defer_lock);
std::unique_lock lk2(dst.mutex, std::defer_lock);
std::lock(lk1, lk2);
Run Code Online (Sandbox Code Playgroud)

std::lock是一个函数,它接受任意数量的Lockable对象并锁定所有对象(或异常中止,在这种情况下它们将全部被解锁)。

std::scoped_lock根据cppreference的说明,它是的包装器std::lock,具有unlock()在其析构函数中调用每个Lockable对象的附加功能。这里不需要添加功能,因为std::shared_lock lk1std::unique_lock lk2也可以用作锁定防护,当它们超出范围时可以解锁其互斥锁。

编辑:各种说明