c++ - 如何理解scoped_lock的析构函数?cppreference会出错吗?
问题描述
~scoped_lock()
{ std::apply([](auto&... __m) { (__m.unlock(), ...); }, _M_devices); }
怎么理解[](auto&... __m) { (__m.unlock(), ...);
?我不了解...
in lambda,也不知道如何以相反的顺序实现释放互斥锁。
正如@HolyBlackCat 所说,
(__m.unlock(), ...)
意思是(__m1.unlock(),(__m2.unlock(), (__m3.unlock(), (...))))
,但它不以相反的顺序实现解锁。
在 cppreference.com 中:
当控制离开创建 scoped_lock 对象的作用域时,scoped_lock 被破坏并以相反的顺序释放互斥锁。
我做了一个实验来确认这一点,如下所示:
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
class mymutex : public std::mutex {
public:
void lock() {
std::mutex::lock();
std::cout << "mutex " << _i << " locked" << std::endl;
}
mymutex(int i): _i(i){}
bool try_lock() {
bool res = std::mutex::try_lock();
if (res) {
std::cout << "mutex " << _i << " try locked" << std::endl;
}
return res;
}
void unlock() {
std::mutex::unlock();
std::cout << "mutex " << _i << " unlocked" << std::endl;
}
private:
int _i;
};
class Speaking {
private:
int a;
mymutex my1;
mymutex my2;
mymutex my3;
public:
Speaking() : a(0), my1(1), my2(2), my3(3){};
~Speaking() = default;
void speak_without_lock();
void speak_with_three_lock();
};
void Speaking::speak_without_lock() {
std::cout << std::this_thread::get_id() << ": " << a << std::endl;
a++;
}
void Speaking::speak_with_three_lock()
{
std::scoped_lock<mymutex, mymutex, mymutex> scoped(my1, my2, my3);
speak_without_lock();
}
int main() {
Speaking s;
s.speak_with_three_lock();
return 0;
}
mutex 1 locked
mutex 2 try locked
mutex 3 try locked
1: 0
mutex 1 unlocked
mutex 2 unlocked
mutex 3 unlocked
那么cppreference会出错吗?
解决方案
我相信 cppreference.com 在这个细节上是不正确的。C++17 说:
~scoped_lock();
效果:对于 [0, sizeof...(MutexTypes)) 中的所有 i,get(pm).unlock()
这意味着释放锁的顺序与它们被获取的顺序相同。
请注意,为了防止死锁,不需要以与获取锁相反的顺序释放锁——只需要始终以相同的顺序获取它们。
推荐阅读
- javascript - 检测更改的样式属性?
- mysql - (mysql) 子查询返回多于 1 行,更新集错误
- java - 扫描仪未立即读取 Next() 或 NextLine()
- input - 如何在输入上使用 ngModel(Angular - TypeScript)
- typo3 - TYPO3 从页面中查找 tt_content
- fonts - Emacs 没有列出半轻字体?
- flutter - 热重载和热重启无法正常工作
- node.js - NodeJS 续集模型问题
- python - API 无法识别向 AWS Boto3 Cognito-idp 传递参数
- python - tensorflow/keras 中两个双向 GRU 层的输出