1. 程式人生 > >c++11實現寫優先的讀寫鎖

c++11實現寫優先的讀寫鎖

先直接貼出程式碼:

#ifndef __WRITE_FIRST_RW_LOCK_H
#define __WRITE_FIRST_RW_LOCK_H

#include <mutex>
#include <condition_variable>

class WfirstRWLock
{
public:
	WfirstRWLock() = default;
	~WfirstRWLock() = default;
public:
	void lock_read()
	{
		std::unique_lock<std::mutex> ulk(counter_mutex);
		cond_r.wait(ulk, [=]()->bool {return write_cnt == 0; });
		++read_cnt;
	}
	void lock_write()
	{
		std::unique_lock<std::mutex> ulk(counter_mutex);
		++write_cnt;
		cond_w.wait(ulk, [=]()->bool {return read_cnt == 0 && !inwriteflag; });
		inwriteflag = true;
	}
	void release_read()
	{
		std::unique_lock<std::mutex> ulk(counter_mutex);
		if (--read_cnt == 0 && write_cnt > 0)
		{
			cond_w.notify_one();
		}
	}
	void release_write()
	{
		std::unique_lock<std::mutex> ulk(counter_mutex);
		if (--write_cnt == 0)
		{
			cond_r.notify_all();
		}
		else
		{
			cond_w.notify_one();
		}
		inwriteflag = false;
	}
	
private:
	volatile size_t read_cnt{ 0 };
	volatile size_t write_cnt{ 0 };
	volatile bool inwriteflag{ false };
	std::mutex counter_mutex;
	std::condition_variable cond_w;
	std::condition_variable cond_r;
};

template <typename _RWLockable>
class unique_writeguard
{
public:
	explicit unique_writeguard(_RWLockable &rw_lockable)
		: rw_lockable_(rw_lockable)
	{
		rw_lockable_.lock_write();
	}
	~unique_writeguard()
	{
		rw_lockable_.release_write();
	}
private:
	unique_writeguard() = delete;
	unique_writeguard(const unique_writeguard&) = delete;
	unique_writeguard& operator=(const unique_writeguard&) = delete;
private:
	_RWLockable &rw_lockable_;
};
template <typename _RWLockable>
class unique_readguard
{
public:
	explicit unique_readguard(_RWLockable &rw_lockable)
		: rw_lockable_(rw_lockable)
	{
		rw_lockable_.lock_read();
	}
	~unique_readguard()
	{
		rw_lockable_.release_read();
	}
private:
	unique_readguard() = delete;
	unique_readguard(const unique_readguard&) = delete;
	unique_readguard& operator=(const unique_readguard&) = delete;
private:
	_RWLockable &rw_lockable_;
};

#endif

        可以看出用c++11實現讀寫鎖變得非常簡潔,在讀取量非常大且寫入頻率很低的時候,通過一個簡單的寫入執行緒計數可以避免大量的 cond_w.notify_one();減少讀取執行緒因此發生的切換。

        這裡需要注意的是對寫操作加鎖時是先增加寫執行緒計數再判斷條件並等待,釋放寫鎖時減少寫執行緒計數並判斷是否還有寫操作等待,如果有隻能喚醒一個寫等待。

        另外,直接使用lock、unlock在c++中是不推薦的,推薦採用RAII方法,即類unique_writeguard、unique_readguard。