Sylar服务器框架---线程同步模块

 1.概述

1.sylar的线程同步模块使用了pthread线程库的互斥量,读写锁,自旋锁。

原子锁是使用的c++的

2.使用了RALL的方法,即资源构造即初始化,出作用域就析构。避免了我们手动进行资源申请和释放的相关操作。

        这里具体的操作是Mutex类创建一个对象时通过构造初始化锁,析构时销毁锁;加锁,解锁两个方法(用户不可自己调用)交由ScopedLockImpl<Mutex>类来调用,ScopedLockedImpl<Mutex>构造时就加锁,析构时解锁。和muduo中的基本一样。这样就不用我们手动加锁解锁了,当锁出了作用域就会自动解锁,销毁,不会出现忘记解锁的情况。

3.相关的锁类都不能进行赋值,拷贝,移动构造等操作,通过私有继承类Noncopyable实现

2.信号量的封装

class Semphore :Noncopyable
	{
	public:
		Semaphore(uint32_t count = 0);

		~semaphore();

		void wait();

		void notify();
	private:
		sem_t m_semphore;

	};

3.互斥量的封装

1.Mutex类构造时初始化锁,销毁锁时析构

2.加锁 ,解锁两个方法(一般不会自己手动调用)交给ScopedLockImpl<Mutex>类来调用

class Mutex :Noncopyable {
	public:
		typedef ScopedLockImpl<Mutex> Lock;

		Mutex()
		{
			pthread_mutex_init(&m_mutex, nullptr);
		}

		~Mutex()
		{
			pthread_mutex_destroy(&m_mutex);
		}

		void lock()  //交给ScopedLockImpl<Mutex>类调用
		{
			pthread_mutex_lock(&m_mutex);
		}

		void unlock()  //交给ScopedLockImpl<Mutex>类调用
		{
			pthread_mutex_unlock(&m_mutex);
		}
	private:
		pthread_mutex_t m_mutex;
	};

1.ScopedLockedImpl<Mutex>类构造时加锁,析构时解锁,从而达到不需要手动加锁解锁的目的

2.这里为什么要写成模板类,因为我们还用到了自旋锁,自旋锁也需要通过这个类模板来进行加锁解锁 (后面会讲到)

template<class T>
	struct ScopedLockImpl
	{
	public:
		ScopedLockImpl(T& mutex) :m_mutex(mutex)
		{
			m_mutex.lock();
			m_locked = true;
		}

		~ScopedLockImpl()
		{
			unlock();
		}

		void lock()  //其实这个方法没用到
		{
			if (!m_locked)
			{
				m_mutex.lock();
				m_locked = true;
			}
		}
		void unlock()
		{
			if (m_locked)
			{
				m_mutex.unlock();
				m_locked = false;
			}
		}
	private:
		T& m_mutex;
		bool m_locked;
	};

4.读写锁的封装

1.为什么用读写锁?

        因为在高并发的场景下,读写操作是很频繁的,而读的频率比较高,使用读写锁来区分操作可以提高效率。

class RWMutex :Noncopyable {
	public:
		typedef ReadScopedLockImpl<RWMutex> ReadLock;
		typedef WriteScopedLockImpl<RWMutex> WriteLock;

		RWMutex()
		{
			ptherad_rwlock_init(&m_lcok, nullptr);
		}
		~RWMutex()
		{
			pthread_rwlock_destroy(&m_lock);
		}
		void rdlock()
		{
			pthread_rwlock_rdlock(&m_lock);
		}
		void wrlock()
		{
			pthread_rwlock_wrlock(&m_lcok);
		}
		void unlock() {
			pthread_rwlock_unlock(&m_lock);
		}

	private:
		pthread_rwlock_t m_lock;


	};

通过局部读锁和局部写锁两个类来进行构造时加锁,析构时解锁 

    template<class T>
	struct ReadScopedLockImpl {  //局部读锁
	public:
		ReadScopedLockImp(T& mutex)
			:m_mutex(mutex) {
			m_mutex.wrlock();
			m_locked = true;
		}

		~ReadScopedLockImpl()
		{
			unlock();
		}

		void lock()
		{
			if (!m_locked)

			{
				m_mutex.wrlock();
				m_locked = true;
			}
		}
		void unlock()
		{
			if (m_locked)
			{
				m_mutex.unlock();
				m_locked = false;
			}
		}
	private:
		T& m_mutex;
		bool m_locked;
	};
	template<class T>
	struct WriteScopedLockImpl {  //局部写锁
	public:
		WriteScopedLockImp(T& mutex)
			:m_mutex(mutex) {
			m_mutex.wrlock();
			m_locked = true;
		}

		~WriteScopedLockImpl()
		{
			unlock();
		}

		void lock()
		{
			if (!m_locked)

			{
				m_mutex.wrlock();
				m_locked = true;
			}
		}
		void unlock()
		{
			if (m_locked)
			{
				m_mutex.unlock();
				m_locked = false;
			}
		}
	private:
		T& m_mutex;
		bool m_locked;
	};

 

5.自旋锁的封装

1.为什么需要自旋锁?

        自旋锁性能高,因为自旋锁加锁失败时,不会让出cpu,而是不断尝试加锁,因此线程不会有上下文的切换,但是因为会占用cpu,所以自旋锁加锁的临界区要尽可能短,提高锁的粒度。

        互斥锁加锁失败会阻塞让出CPU的使用权,线程会有上下文的切换

 

class Spinlock :Noncopyable {
	public:
		typedef ScopedLockImpl<Spinlock> Lock;
		Spinlock()
		{
			pthread_spin_init(&m_mutex, 0);
		}
		~Spinlock()
		{
			pthread_spin_destroy(&m_mutex);
		}
		void lock()
		{
			pthread_spin_lock(&m_mutex);
		}
		void unlock()
		{
			pthread_spin_unlock(&m_mutex);
		}
	private:
		pthread_spinlock_t m_mutex;
	};

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值