[英]shared_mutex lock ordering
我的印象是,如果获得了太多的共享锁,那么使用c ++ 17的std::shared_mutex
实现的多个读者/单个编写器模式可能永远不会放弃唯一锁。
在挖掘cppreference之后 ,我不确定是这样的。 特别是:
单个互斥锁上的所有锁定和解锁操作都在一个总订单中进行
例如,给定shared_mutex
上的以下操作,我相信unique_lock
可能永远不会获取。 假设shared_locks
限量的shared_locks
,并且这些锁在第一个shared_locks
发布之前获取。
shared_lock
shared_lock
shared_lock
unique_lock
shared_lock
[...]
shared_lock
具有以下特点。
{ shared_lock, shared_lock, shared_lock, shared_lock, ..., shared_lock } // never releases
unique_lock
但是,如果我正确理解cppreference,一旦unique_lock
尝试获取,连续的shared_locks
将阻塞,直到unique_lock
被释放。 给出以下线程特征。
{ shared_lock, shared_lock, shared_lock} // simultaneous
unique_lock
{ shared_lock, ..., shared_lock} // waits, then simultaneous
所以我的问题是, std::shared_mutex
在共享锁和唯一锁之间保持排序? 防止由于获取了大量的shared_locks
而永远不会获取unique_locks
的情况。
编辑:
这是一个帮助理解问题的代码示例,为了后人的缘故。 在MSVC 2019上, shared_mutex
是安全的,并且根据需要进行排序。 unique_lock
确实在“无限”数量的shared_locks
之前得到处理。
现在的问题是,这个平台是否依赖?
#include <chrono>
#include <cstdio>
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <vector>
using namespace std::chrono_literals;
std::shared_mutex smtx;
int main(int, char**) {
std::vector<std::thread> threads;
auto read_task = [&]() {
std::shared_lock l{ smtx };
printf("read\n");
std::this_thread::sleep_for(1s);
};
auto write_task = [&]() {
std::unique_lock l{ smtx };
printf("write\n");
std::this_thread::sleep_for(1s);
};
// Create a few reader tasks.
threads.emplace_back(read_task);
threads.emplace_back(read_task);
threads.emplace_back(read_task);
// Try to lock a unique_lock before read tasks are done.
std::this_thread::sleep_for(1ms);
threads.emplace_back(write_task);
// Then, enque a gazillion read tasks.
// Will the unique_lock be locked? [drum roll]
// Would be while(true), 120 should be enough for demo
for (size_t i = 0; i < 120; ++i) {
std::this_thread::sleep_for(1ms);
threads.emplace_back(read_task);
}
for (auto& t : threads) {
t.join();
}
}
产出:
read
read
read
write
read
...
read
std shared_mutex
规范未指定共享锁的优先级,也不指定唯一锁。 也没有任何API可以设置这样的优先级。 缺乏优先权规范的原始动机之一是存在如此处所解释的Alexander Terekhov算法 。
第二个动机是解释shared_mutex中缺少读写器优先级策略。 这是由于算法归功于Alexander Terekhov,它让操作系统决定下一个获得锁定的线程,而不关心是否正在寻找一个独特的锁或共享锁。 这导致完全缺乏读者或作家的饥饿。 这很公平。
标准规范不需要Alexander Terekhov算法。 然而,至少我希望,这种算法将是首选,因为缺乏规范或API优先于读者而不是编写者,反之亦然。
有关Alexander Terekhov算法的更多细节以及一些代码,这些代码在此SO答案中展示了它的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.