字节有一道面试题:
使用普通的互斥锁实现读写锁
要向用mutex锁设计,首先要知道什么是读写锁。 读写锁的定义如下:
a readers–writer is a synchronization primitive that solves one of the readers–writers problems. An RW lock allows concurrent access for read-only operations, whereas write operations require exclusive access.
这里给出C++11版本的读写锁实现,参考了这个网站
class RWMutex
{
std::mutex mut_;
std::condition_variable gate1_;
std::condition_variable gate2_;
unsigned state_;
static const unsigned write_entered_ = 1U << (sizeof(unsigned)*CHAR_BIT - 1);
static const unsigned n_readers_ = ~write_entered_;
public:
() : state_(0){}
RWMutex~RWMutex(){}
(const RWMutex&) = delete;
RWMutex& operator=(const RWMutex &) = delete;
RWMutex
void lock() {
//std::this_thread::disable_interruption _; std::thread 不可打断,但是std::jthread 可能会被打断
std::unique_lock<std::mutex> lk(mut_);
gate1_.wait(lk, [&](){return !is_write_entered();} ); // 要先保证没有写者进入
state_ |= write_entered_;
gate2_.wait(lk,[&](){return get_readers_num() == 0;}); // 要保证没有读者进入
}
bool try_lock() {
std::unique_lock<std::mutex> lk(mut_, std::try_to_lock);
if (lk.owns_lock() && state_ == 0)
{
state_ = write_entered_;
return true;
}
return false;
}
void unlock()
{
{
std::lock_guard<std::mutex> _(mut_);
state_ = 0;
}
gate1_.notify_all();
}
// Shared ownership
void lock_shared() {
//std::this_thread::disable_interruption _;
std::unique_lock<std::mutex> lk(mut_);
gate1_.wait(lk,[]{ return !is_write_entered() && get_readers_num() < n_readers_; });
unsigned num_readers = get_readers_num() + 1;
(num_readers);
set_readers_num}
inline unsigned get_readers_num(){
return state_ & n_readers_;
}
inline bool is_write_entered(){
return state_ & write_entered_;
}
inline void set_readers_num(unsigned num_readers){
state_ &= ~n_readers_;
state_ |= num_readers;
}
bool try_lock_shared() {
std::unique_lock<std::mutex> lk(mut_, std::try_to_lock);
unsigned num_readers = get_readers_num();
if (lk.owns_lock() && !is_write_entered() && num_readers != n_readers_)
{
++num_readers;
(num_readers);
set_readers_numreturn true;
}
return false;
}
void unlock_shared() {
std::lock_guard<std::mutex> _(mut_);
unsigned num_readers = get_readers_num() - 1;
(num_readers);
set_readers_numif (is_write_entered())
{
if (num_readers == 0)
gate2_.notify_one(); // 唤醒等待的写者
}
else
{
if (num_readers == n_readers_ - 1)
gate1_.notify_one(); // 如果读成员满了之后开始释放,就唤醒等待的读者
}
}
};