[英]Can scoped_lock lock a shared_mutex in read mode?
C++17 introduced both std::shared_mutex
and std::scoped_lock
. C ++ 17引入了
std::shared_mutex
和std::scoped_lock
。 My problem is now, that it seems, that scoped_lock
will lock a shared mutex always in exclusive (writer) mode, when it is passed as an argument, and not in shared (reader) mode. 我现在的问题是,
scoped_lock
似乎总是在独占(写入)模式下锁定共享互斥锁,当它作为参数传递时,而不是共享(读取器)模式。 In my app, I need to update an object dst
with data from an object src
. 在我的应用程序中,我需要使用来自对象
src
数据更新对象dst
。 I want to lock src
shared and dst
exclusive. 我想锁定
src
shared和dst
exclusive。 Unfortunately, this has the potential for deadlock, if a call to another update method with src
and dst
switched occurs at the same time. 不幸的是,如果同时调用
src
和dst
切换的另一个更新方法,则可能会出现死锁。 So I would like to use the fancy deadlock avoidance mechanisms of std::scoped_lock
. 所以我想使用
std::scoped_lock
的花哨的死锁避免机制。
I could use scoped_lock
to lock both src
and dst
in exclusive mode, but that unnecessarily strict lock has performance backdraws elsewhere. 我可以使用
scoped_lock
以独占模式锁定src
和dst
,但是不必要的严格锁定会在其他地方进行性能回退。 However, it seems, that it is possible to wrap src
's shared_mutex
into a std::shared_lock
and use that with the scoped_lock
: When the scoped_lock
during its locking action calls try_lock()
on the shared_lock
, the later will actually call try_shared_lock()
on src
's shared_mutex
, and that's what I need. 但是,似乎可以将
src
的shared_mutex
包装到std::shared_lock
并将其与scoped_lock
一起使用:当scoped_lock
在其锁定操作期间调用shared_lock
上的try_lock()
时,后者将实际调用try_shared_lock()
在src
的shared_mutex
,这就是我需要的东西。
So my code looks as simple as this: 所以我的代码看起来很简单:
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???
}
Is it safe to use a (shared) lock guard like this inside another (deadlock avoidance) lock guard? 在另一个(死锁避免)锁定防护装置中使用这样的(共享)锁定防护装置是否安全?
As pointed out by various commentators, who have read the implementation code of the C++ standard library: Yes, the use of a std::shared_mutex
wrapped inside a std::shared_lock()
as one of the arguments to std::scoped_lock()
is safe. 正如各种评论员所指出的,他们已经阅读了C ++标准库的实现代码:是的,使用
std::shared_mutex
作为std::scoped_lock()
的参数之一包装在std::shared_lock()
std::scoped_lock()
是安全的。
Basically, a std::shared_lock
forwards all calls to lock()
to lock_shared()
on the mutex. 基本上,
std::shared_lock
lock_shared()
lock()
所有调用转发到互斥lock_shared()
。
std::shared_lock::lock -----------> mutex()->lock_shared(). // same for try_lock etc..
Another possible solution 另一种可能的解决
std::shared_lock lk1(src.mutex, std::defer_lock);
std::unique_lock lk2(dst.mutex, std::defer_lock);
std::lock(lk1, lk2);
std::lock
is a function that accepts any number of Lockable
objects and locks all of them (or aborts with an exception, in which case they will all be unlocked). std::lock
是一个函数,它接受任意数量的Lockable
对象并锁定所有这些对象(或者中止异常,在这种情况下它们都将被解锁)。
std::scoped_lock
according to cppreference is a wrapper for std::lock
, with the added functionaliy of calling unlock()
on each Lockable object in its destructor. 根据cppreference的
std::scoped_lock
是std::lock
的包装器,添加了在析构函数中对每个Lockable对象调用unlock()
功能。 That added functionality is not required here, as std::shared_lock lk1
and std::unique_lock lk2
also work as lock guards, that unlock their mutexes, when they go out of scope. 这里不需要添加功能,因为
std::shared_lock lk1
和std::unique_lock lk2
也可以作为锁定保护,当它们超出范围时解锁它们的互斥锁。
Edit: various clarifications 编辑:各种澄清
Mutex : Add thread safety to shared resources Mutex :为共享资源添加线程安全性
Lock : Add RAII (and possibly extra functionality) to mutex 锁定 :将RAII(可能还有其他功能)添加到互斥锁
Different locks let you lock the mutex in different ways: 不同的锁允许您以不同的方式锁定互斥锁:
scoped_lock
is a bare bone exclusive lock that is locked when constructed and unlocked when destroyed. scoped_lock
是一个裸骨独占锁,在构造时锁定,在销毁时解锁。 unique_lock
and shared_lock
are exclusive and shared locks respectively that are also locked and unlocked with their default constructor and destructor. unique_lock
和shared_lock
分别是独占锁和共享锁,它们也使用默认构造函数和析构函数锁定和解锁。 However, they also provide extra functionality. 但是,它们还提供额外的功能。 For example, you can try to luck them , or you can unlock them before they are destroyed.
例如,你可以尝试运气 ,或者你可以在它们被销毁之前解锁它们。
So a typical use case would be to use a shared_lock
for shared access (when multiple threads read the same resource), and use a unique_lock
or a scoped_lock
for exclusive access (depending on if you need the extra features of unique_lock
or not). 因此,典型的用例是使用
shared_lock
进行共享访问(当多个线程读取相同的资源时),并使用unique_lock
或scoped_lock
进行独占访问(取决于您是否需要unique_lock
的额外功能)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.