1. 程式人生 > >STL實現讀寫鎖

STL實現讀寫鎖

在這裡不考慮std::shared_mutex, 只用條件變數和std::mutex來實現。

分析讀寫鎖的邏輯:

讀鎖之間是不衝突的,無論多少個執行緒申請讀鎖,不需要等待。但是要想獲得寫鎖,就必須等所有的讀鎖全部釋放完畢。那麼怎麼知道所有的讀全部結束了呢?只能用一個int變數去記錄讀鎖的總數。這個變數變為0意味著所有的讀都結束了。所以,寫鎖的條件變數的寫法類似於:

		while (readerCount != 0)
		{
			cv.wait(lock);
		}
但這是不完善的,如果其他執行緒也在寫呢?寫鎖也必須等待寫操作結束。那麼寫鎖是否也需要int型來統計總數呢?不需要。bool型足矣。因此可以改為:
		while (readerCount != 0 || writerUsed == true)
		{
			cv.wait(lock);
		}
讀鎖只需要檢測是否有寫操作,遞增寫的個數:
		while (writerUsed == true)
		{
			cv.wait(lock);
		}
		readerCount++;

讀鎖通知和寫鎖通知的時機也不同。讀鎖要等所有的讀全部結束的時候進行通知,寫鎖則是每個寫結束都要通知。

	void unlockReader()
	{
		std::unique_lock<std::mutex> lock(m);
		readerCount--;
		if (readerCount == 0)
		{
			cv.notify_all();
		}
	}
	void unlockWriter()
	{
		std::unique_lock<std::mutex> lock(m);
		writerUsed = false;
		cv.notify_all();
	}

所有的程式碼:
class rwLock
{
public:
	void getReadLock()
	{
		std::unique_lock<std::mutex> lock(m);
		while (writerUsed == true)
		{
			cv.wait(lock);
		}
		readerCount++;
	}
	void getWriteLock()
	{
		std::unique_lock<std::mutex> lock(m);
		while (readerCount != 0 || writerUsed == true)
		{
			cv.wait(lock);
		}
		writerUsed = true;
	}
	void unlockReader()
	{
		std::unique_lock<std::mutex> lock(m);
		readerCount--;
		if (readerCount == 0)
		{
			cv.notify_all();
		}
	}
	void unlockWriter()
	{
		std::unique_lock<std::mutex> lock(m);
		writerUsed = false;
		cv.notify_all();
	}

private:
	int readerCount = 0;
	bool writerUsed = false;
	std::mutex m;
	std::condition_variable cv;
};