boost::shared_mutex
或std::shared_mutex
(C ++ 17)可用于单写多读访问。作为教育练习,我编写了一个简单的实现,使用自旋锁并具有其他限制(例如公平策略),但显然不适用于实际应用。
这个想法是互斥量保持引用计数,如果没有线程持有锁,则引用计数为零。如果> 0,则该值表示可以访问的读者数量。如果为-1,则单个写入者可以访问。
这是一个正确的实现(特别是使用了最小的内存顺序),没有数据竞争吗?
#include <atomic>
class my_shared_mutex {
std::atomic<int> refcount{0};
public:
void lock() // write lock
{
int val;
do {
val = 0; // Can only take a write lock when refcount == 0
} while (!refcount.compare_exchange_weak(val, -1, std::memory_order_acquire));
// can memory_order_relaxed be used if only a single thread takes write locks ?
}
void unlock() // write unlock
{
refcount.store(0, std::memory_order_release);
}
void lock_shared() // read lock
{
int val;
do {
do {
val = refcount.load(std::memory_order_relaxed);
} while (val == -1); // spinning until the write lock is released
} while (!refcount.compare_exchange_weak(val, val+1, std::memory_order_acquire));
}
void unlock_shared() // read unlock
{
// This must be a release operation (see answer)
refcount.fetch_sub(1, std::memory_order_relaxed);
}
};
lock_shared
不能解锁共享的互斥锁;如果已经在未加锁状态下,它只能获取读锁。你对于unlock_shared
中的顺序是正确的,它必须是一个释放操作。 - LWimsey