[英]std::lock_guard and std::adopt_lock behaviour without locking the mutex
I have been learning about the usage of std::lock
and std::lock_guard
and most examples follow the pattern below:我一直在学习
std::lock
和std::lock_guard
的用法,大多数示例都遵循以下模式:
std::lock(m1, m2);
std::lock_guard<std::mutex> guard1(m1, std::adopt_lock);
std::lock_guard<std::mutex> guard2(m2, std::adopt_lock);
//Do something here
Then I came across an example that utilized the same pattern you would use if you were using std::unique_lock
, but with lock_guard
:然后我遇到了一个示例,该示例使用了与使用
std::unique_lock
使用的相同模式,但使用了lock_guard
:
std::lock_guard<std::mutex> guard1(m1, std::adopt_lock);
std::lock_guard<std::mutex> guard2(m2, std::adopt_lock);
std::lock(m1, m2);
//Do something here
My question is, would this cause undefined behaviour if you use the second pattern and an exception occurs before you reach std::lock
?我的问题是,如果您使用第二种模式并且在到达
std::lock
之前发生异常,这会导致未定义的行为吗?
PS I am aware that C++17 introduced std::scoped_lock
and that std::lock_guard
is still around mainly for compatibility with older code. PS 我知道 C++17 引入了
std::scoped_lock
并且std::lock_guard
仍然存在,主要是为了与旧代码兼容。
Your second example is undefined behavior;你的第二个例子是未定义的行为;
adopt_lock
constructor presumes that the mutex is already held. adopt_lock
构造函数假定互斥锁已经被持有。 This UB is triggered at construction, not at destruction or when an exception is thrown.这个 UB 在构造时触发,而不是在销毁或抛出异常时触发。
If you used unique_lock
instead of scoped_lock
, it has a:如果您使用
unique_lock
而不是scoped_lock
,则它具有:
unique_lock( mutex_type& m, std::defer_lock_t t ) noexcept;
constructor, which permits your std::lock
use with a slight change:构造函数,它允许您使用
std::lock
稍作更改:
std::unique_lock<std::mutex> guard1(m1, std::defer_lock);
std::unique_lock<std::mutex> guard2(m2, std::defer_lock);
std::lock(guard1, guard2);
Now, unique_lock
does track if it has the lock, so there is possible memory and performance overhead;现在,
unique_lock
会跟踪它是否有锁,因此可能存在内存和性能开销; if unique_lock
s are local to the scope, compilers can and will optimize out that if it can prove it safe.如果
unique_lock
是作用域本地的,编译器可以并且会优化它,如果它可以证明它是安全的。
And if the compiler can't prove it safe, quite often it isn't safe.如果编译器不能证明它是安全的,那么它通常是不安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.