使用mutex和condition实现一个读优先的读写锁
#include <mutex>
#include <chrono>
#include <thread>
#include <iostream>
#include <time.h>
class WriteFirstRWLock
{
public:
WriteFirstRWLock() : waitWCount_(0), wCount_(0), rCount_(0) {}
~WriteFirstRWLock() {}
void ReadLock()
{
std::unique_lock<std::mutex> lk(mutex_);
// 这个0 < wCount_判断条件就保证了如果当前有ReadLock和WriteLock竞争,
// ReadLock这个wait即使被唤醒也会因为不满足break while循环的条件而再次进入wait
// 保证Write操作优先
// 而且正因为上面的情景,只能notify_all不能notify_one
//printf("before read wait wCount_: %d, waitWCount_: %d\n", wCount_, waitWCount_);
while (0 < wCount_ || 0 < waitWCount_)
{
cond_.wait(lk);
//printf("after read wait, wCount_: %d, waitWCount_: %d\n", wCount_, waitWCount_);
}
++rCount_;
}
void ReadUnLock()
{
std::unique_lock<std::mutex> lk(mutex_);
--rCount_;
cond_.notify_all();
}
void WriteLock()
{
std::unique_lock<std::mutex> lk(mutex_);
++waitWCount_;
// printf("before write wait, rCount_: %d, wCount_: %d\n", rCount_, wCount_);
while (0 < rCount_ || 0 < wCount_)
{
cond_.wait(lk);
// printf("after write wait, rCount_: %d, wCount_: %d\n", rCount_, wCount_);
}
--waitWCount_;
++wCount_;
}
void WriteUnlock()
{
std::unique_lock<std::mutex> lk(mutex_);
--wCount_;
cond_.notify_all();
}
WriteFirstRWLock(const WriteFirstRWLock&) = delete;
WriteFirstRWLock& operator=(const WriteFirstRWLock&) = delete;
private:
int32_t waitWCount_; // waiting for writing
int32_t wCount_; // writing count
int32_t rCount_; // reading count
std::mutex mutex_;
std::condition_variable cond_;
};
inline time_t GetTimeStamp()
{
time_t rawTime = ::time(&rawTime);
return rawTime;
}
static void func1(WriteFirstRWLock& lock)
{
while (true)
{
// write
lock.WriteLock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
lock.WriteUnlock();
}
}
static void func2(WriteFirstRWLock* const lock)
{
while (true)
{
// read
lock->ReadLock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
lock->ReadUnLock();
}
}
int main()
{
WriteFirstRWLock rwlock;
//std::thread thread1(func1, &rwlock);
std::thread thread1(func1, std::ref(rwlock));
std::thread thread2(func2, &rwlock);
std::thread thread3(func2, &rwlock);
std::thread thread4(func2, &rwlock);
thread1.join();
thread2.join();
thread3.join();
thread4.join();
return 0;
}