c++11 读写锁实现

发布于:2024-10-12 ⋅ 阅读:(143) ⋅ 点赞:(0)

 在一些读多写少的业务场景下,读写锁的效率是高于互斥锁的,然而c++到c++14才有读写锁,如果想在c++11中实现一套读写锁,可以参考以下实现:

//file: SharedMutex.h
#pragma once
#include <mutex>
#include <condition_variable>
class CSharedMutex
	{
	public:
		CSharedMutex();

		void lock();

		bool try_lock();

		void unlock();

		void lock_shared();

		bool try_lock_shared();

		void unlock_shared();

	protected:
	private:

		CSharedMutex(const CSharedMutex&);
		const CSharedMutex& operator=(const CSharedMutex&);

		class CStateData
		{
		public:
			CStateData();

			bool m_bExclusive;
			unsigned int m_uSharedCount;
			unsigned int m_uExclusiveWaitingBlockedCount;
		protected:
		private:
		};


		CStateData m_cState;
		std::mutex m_cMutex;
		std::condition_variable_any m_condShared;
		std::condition_variable_any m_condExclusive;
	};
//file: SharedMutex.cpp
#include "SharedMutex.h"
void CSharedMutex::lock()
	{
		bool bBlock = false;
		std::unique_lock<std::mutex> cLock(m_cMutex);
		while (m_cState.m_uSharedCount>0 || m_cState.m_bExclusive)  //共享读/独占写则等待
		{
			if (!bBlock)
			{
				m_cState.m_uExclusiveWaitingBlockedCount++;
				bBlock = true;
			}
			m_condExclusive.wait(cLock);
		}
		if (bBlock)
		{
			m_cState.m_uExclusiveWaitingBlockedCount--;
		}
		m_cState.m_bExclusive = true;
	}

	bool CSharedMutex::try_lock()
	{
		std::unique_lock<std::mutex> cLock(m_cMutex);
		if (m_cState.m_uSharedCount > 0 || m_cState.m_bExclusive)  //有读、或者写 -> 无法加锁
		{
			return false;
		}
		else
		{
			m_cState.m_bExclusive = true;
			return true;
		}
	}
	void CSharedMutex::unlock()
	{
		std::unique_lock<std::mutex> cLock(m_cMutex);
		m_cState.m_bExclusive = false;  // 写结束
		if (m_cState.m_uExclusiveWaitingBlockedCount > 0)
		{
			m_condExclusive.notify_one();  // 有写等待,通知一个写
		}
		else
		{
			m_condShared.notify_all();  // 没有写等待,唤醒所有读
		}
	}
	void CSharedMutex::lock_shared()
	{
		std::unique_lock<std::mutex> cLock(m_cMutex);
		while (m_cState.m_bExclusive || m_cState.m_uExclusiveWaitingBlockedCount > 0)  //有写或者写等待 -> 就进入读等待
		{
			m_condShared.wait(cLock);
		}
		m_cState.m_uSharedCount++;
	}
	bool CSharedMutex::try_lock_shared()
	{
		std::unique_lock<std::mutex> cLock(m_cMutex);
		if (m_cState.m_bExclusive || m_cState.m_uExclusiveWaitingBlockedCount > 0)  // 有写或者写等待 -> 无法共享读
		{
			return false;
		}
		else
		{
			m_cState.m_uSharedCount++;
			return true;
		}
	}
	void CSharedMutex::unlock_shared()
	{
		std::unique_lock<std::mutex> cLock(m_cMutex);
		m_cState.m_uSharedCount--;
		if (m_cState.m_uSharedCount == 0 && m_cState.m_uExclusiveWaitingBlockedCount > 0)  // 最后一个读且有写等待->通知写
		{
			m_condExclusive.notify_one();
		}
	}

	CSharedMutex::CSharedMutex()
	{

	}

	CSharedMutex::CStateData::CStateData()
		: m_uSharedCount(0)
		, m_bExclusive(false)
		, m_uExclusiveWaitingBlockedCount(0)
	{

	}

 

// ShareadGuard.h
#pragma once
#include "SharedMutex.h"

template<typename T>
	class UniqueLock
	{
	public:
		UniqueLock(T &cMutex)
			:m_cMutex(cMutex)
			, m_bLocked(true)
		{
			m_cMutex.lock();
		}

		~UniqueLock()
		{
			UnLock();
		}

		void Lock()
		{
			if (!m_bLocked)
			{
				m_cMutex.lock();
				m_bLocked = true;
			}
		}

		void UnLock()
		{
			if (m_bLocked)
			{
				m_cMutex.unlock();
				m_bLocked = false;
			}
		}
	protected:
	private:
		UniqueLock(const UniqueLock&);
		const UniqueLock & operator=(const UniqueLock&);
		
		T &m_cMutex;
		bool m_bLocked;
	};


	template<typename T>
	class SharedLock
	{
	public:
		SharedLock(T &cMutex)
			: m_cMutex(cMutex)
			, m_bLocked(true)
		{
			m_cMutex.lock_shared();
		}

		~SharedLock()
		{
			UnLock();
		}

		void Lock()
		{
			if (!m_bLocked)
			{
				m_cMutex.lock_shared();
				m_bLocked = true;
			}
		}

		void UnLock()
		{
			if (m_bLocked)
			{
				m_cMutex.unlock_shared();
				m_bLocked = false;
			}
		}

	private:
		SharedLock(const SharedLock &);
		const SharedLock & operator=(const SharedLock &);

	private:
		T &m_cMutex;
		bool m_bLocked;
	};

 

//file: main.cpp

#include "SharedMutex.h"
#include "ShareadGuard.h"


int main()
{
    CSharedMutex mtx;
    SharedLock<CSharedMutex> rGuard(mtx);// 读锁, 尝试以共享的方式上锁,如果此前有其他人独占了锁,此处将阻塞
    UniqueLock<CSharedMutex> wGuard(mtx);// 写锁,尝试以独占的方式上锁,如果此前有其他人以任何方式上了锁,此处将阻塞
    return 0;
}

 

 


网站公告

今日签到

点亮在社区的每一天
去签到