很久以前我用一个互斥锁和一个条件变量实现了读写锁,认为这应该是读写锁最简洁的实现了吧。可是今天在阅读《深入理解计算机系统》第二版的12.5节时,才发现只使用互斥锁就能实现读写锁。书中使用了两个互斥锁实现读写锁,其中一个互斥锁允许一个线程加锁而另一个线程解锁,完全颠覆了我对互斥锁用法的固有思维,感觉妙不可言。
本文用c++封装了读写锁的两种实现,其中mutex和condition_variable分别表示互斥锁和条件变量的伪代码类。
一、使用互斥锁和条件变量实现读写锁:
class readwrite_lock { public: readwrite_lock() : stat(0) { } void readLock() { mtx.lock(); while (stat < 0) cond.wait(mtx); ++stat; mtx.unlock(); } void readUnlock() { mtx.lock(); if (--stat == 0) cond.notify_one(); // 叫醒一个等待的写操作 mtx.unlock(); } void writeLock() { mtx.lock(); while (stat != 0) cond.wait(mtx); stat = -1; mtx.unlock(); } void writeUnlock() { mtx.lock(); stat = 0; cond.notify_all(); // 叫醒所有等待的读和写操作 mtx.unlock(); } private: mutex mtx; condition_variable cond; int stat; // == 0 无锁;> 0 已加读锁个数;< 0 已加写锁 };
二、使用2个互斥锁实现读写锁:
class readwrite_lock { public: readwrite_lock() : read_cnt(0) { } void readLock() { read_mtx.lock(); if (++read_cnt == 1) write_mtx.lock(); read_mtx.unlock(); } void readUnlock() { read_mtx.lock(); if (--read_cnt == 0) write_mtx.unlock(); read_mtx.unlock(); } void writeLock() { write_mtx.lock(); } void writeUnlock() { write_mtx.unlock(); } private: mutex read_mtx; mutex write_mtx; int read_cnt; // 已加读锁个数 };