c++读写锁实现
- C++17,提供了shared_mutex。配合C++14,提供的shared_lock。及C++11,提供的 unique_lock, 可以方便实现读写锁。
- 但上述的前提是,允许你使用C++17。在国内的开发环境下,别说C++17,连C++11用的也不多。
- 所以,大多数时候,我们需要自己实现一套C++读写锁(C++11环境下)。
代码实现
- RWLock.h
#ifndef RWLOCK__H
#define RWLOCK__H
#ifndef __cplusplus
# error ERROR: This file requires C++ compilation(use a .cpp suffix)
#endif
#include <mutex>
#include <condition_variable>
namespace linduo {
class RWLock {
public:
RWLock();
virtual ~RWLock() = default;
void lockWrite();
void unlockWrite();
void lockRead();
void unlockRead();
private:
volatile int m_readCount;
volatile int m_writeCount;
volatile bool m_isWriting;
std::mutex m_Lock;
std::condition_variable m_readCond;
std::condition_variable m_writeCond;
};
class ReadGuard {
public:
explicit ReadGuard(RWLock& lock);
virtual ~ReadGuard();
private:
ReadGuard(const ReadGuard&);
ReadGuard& operator=(const ReadGuard&);
private:
RWLock &m_lock;
};
class WriteGuard {
public:
explicit WriteGuard(RWLock& lock);
virtual ~WriteGuard();
private:
WriteGuard(const WriteGuard&);
WriteGuard& operator=(const WriteGuard&);
private:
RWLock& m_lock;
};
} /* namespace linduo */
#endif // RWLOCK__H
- RWLock.cpp
#include "RWLock.h"
namespace linduo {
RWLock::RWLock()
: m_readCount(0)
, m_writeCount(0)
, m_isWriting(false) {
}
void RWLock::lockRead() {
std::unique_lock<std::mutex> gurad(m_Lock);
m_readCond.wait(gurad, [=] { return 0 == m_writeCount; });
++m_readCount;
}
void RWLock::unlockRead() {
std::unique_lock<std::mutex> gurad(m_Lock);
if (0 == (--m_readCount)
&& m_writeCount > 0) {
// One write can go on
m_writeCond.notify_one();
}
}
void RWLock::lockWrite() {
std::unique_lock<std::mutex> gurad(m_Lock);
++m_writeCount;
m_writeCond.wait(gurad, [=] { return (0 == m_readCount) && !m_isWriting; });
m_isWriting = true;
}
void RWLock::unlockWrite() {
std::unique_lock<std::mutex> gurad(m_Lock);
m_isWriting = false;
if (0 == (--m_writeCount)) {
// All read can go on
m_readCond.notify_all();
} else {
// One write can go on
m_writeCond.notify_one();
}
}
ReadGuard::ReadGuard(RWLock &lock)
: m_lock(lock) {
m_lock.lockRead();
}
ReadGuard::~ReadGuard() {
m_lock.unlockRead();
}
WriteGuard::WriteGuard(RWLock &lock)
: m_lock(lock) {
m_lock.lockWrite();
}
WriteGuard::~WriteGuard() {
m_lock.unlockWrite();
}
} /* namespace linduo */
- 使用
RWLock m_Lock;
void func() {
// 写锁
WriteGuard autoSync(m_Lock);
}
void func() {
// 读锁
ReadGuard autoSync(m_Lock);
}