Daily C/C++ 利用mutex实现简单的读写锁
之前我们有说过条件变量相关的东西,他可以帮助我们控制线程的执行
今天这里,我们就说一种简单的利用mutex和条件变量实现读写锁的方法
这里的实现其实就是CMU15445的bustub中的实现,如果有兴趣的同学可以自己去看相关的代码
首先我们要明确,我们希望实现的读写锁的性质。比如他是按照队列一个一个分配的吗?他是读者优先还是写者优先?
这里,我们要实现的读写锁是写者优先,即如果当前有写者在等待,那么新到来的读者也会被阻塞。
如果当前有写者的时候,我们又来一个写者,怎么办?如果我们始终将锁分配给写者,会不会导致饿死的现象呢?
鉴于这种情况,当目前有一个写者的时候,新来的写者将作为读者与其他读者一同竞争。当新的写者竞争到锁的时候,他就会阻塞新的读者,然后等待现有的读者结束,从而开始他自己的任务。
看起来是一个比较合理的策略,我们来看看代码
/**
* Acquire a write latch.
*/
void WLock() {
std::unique_lock<mutex_t> latch(mutex_);
while (writer_entered_) {
reader_.wait(latch);
}
writer_entered_ = true;
while (reader_count_ > 0) {
writer_.wait(latch);
}
}
/**
* Release a write latch.
*/
void WUnlock() {
std::lock_guard<mutex_t> guard(mutex_);
writer_entered_ = false;
reader_.notify_all();
}
/**
* Acquire a read latch.
*/
void RLock() {
std::unique_lock<mutex_t> latch(mutex_);
while (writer_entered_ || reader_count_ == MAX_READERS) {
reader_.wait(latch);
}
reader_count_++;
}
/**
* Release a read latch.
*/
void RUnlock() {
std::lock_guard<mutex_t> guard(mutex_);
reader_count_--;
if (writer_entered_) {
if (reader_count_ == 0) {
writer_.notify_one();
}
} else {
if (reader_count_ == MAX_READERS - 1) {
reader_.notify_one();
}
}
}
其实是很简单的四块逻辑,我们一个一个看
WLock
会首先判断当前有没有写者正在操作或者等待,如果有的话,那么新的写者就会在读者的条件变量中进行等待,意为等待写者
由此也可以看出,读者和写者的条件变量并不是单独给这两种角色准备的,而是根据含义来分配。如果我们在等待写者,我们就要分配到读者条件变量中。如果我们在等待读者,我们自然就要分配到写者的条件变量中。
当轮到新的写者被唤醒的时候,他会检查当前是否有写者在进行操作,因为有可能出现有多个写者在等待一个写者的情况。然后他会设置writer_entered_
,这会告诉其他的线程,现在有一个写者在等待操作了。然后他就会在写者的条件变量中等待,等待当前所有的读者都结束后,他就会获取这个锁。
WUnlock
则是对应的解锁,他会设置writer_entered_
为false,告诉其他的线程写者的操作都已经结束了。然后在读者的条件变量上唤醒所有的读者
RLock
会首先判断,如果当前有写者在等待,那么他就会进入读者的等待队列中,等待写者结束操作。或者当读者的数量到达一个限值的时候,他也会进入等待。同时,读者会维护一个reader_count_
用来代表当前读者的数量
RUnlock
同样也会维护读者的数量。同时他会判断,如果当前有写者在等待,同时这个读者是最后一个读者了,那么他就会唤醒这个写者。
否则的话,只有在超出读者上限的时候才会出现读者等读者的情况,这时候他会唤醒一个等待的读者线程。
基本的功能都解析完了,然后我们看看他是怎么实现我们上述的那些特性的
写者优先我们已经可以看到了,当读者发现有写者正在等待或者正在操作的时候,他会进入等待。
对于多个写者的情况,新的写者们就会在读者的条件变量中等待。一旦执行了WUnlock
,唤醒了所有的读者线程,那么优先获得锁的写者就会将writer_entered_
设为真,从而阻塞其他所有的线程。然后他就会在写者队列中等待读者完成任务,从而获取锁。
大概的介绍就是这样了,不得不说实现的确实非常巧妙。十分感谢Andy为我们带来这样优秀的学习资源
文章评论
nb啊老板