C++并发编程学习02:互斥元分层机制保证并发

互斥元层级

本文内容摘记与“C++并发编程实战”

#pragma once
#include<mutex>

/*
* 封装当前互斥元所在的层级的信息
* 对互斥元进行分层级管理
*/
class HierarchicalMutex
{
private:
	std::mutex m_mutex;
	unsigned long const m_hierarchy_value; //当前即将请求的互斥元所在层级
	unsigned long m_previous_hierarchy_value; //当前互斥元前一个互斥元所在的层级
	// 当前线程拥有该互斥元所在的层级
	// thread_local 修饰的变量具有线程周期
	// 这些变量在线程开始的时候被生成 线程结束时被销毁
	// 每个线程拥有一个独立的变量实例
	// 存储周期:automatic static dynamic thread
	static thread_local unsigned long m_this_thread_hierarchy_value;

	/*检查是否违反层级关系*/
	/*当前线程所获取的互斥元的层级比即将请求的互斥元的层级低:则不允许其去请求高层次的互斥元*/
	void check_for_hierarchy_violation()
	{
		// 当前线程的层级比m_hierarchy_value低
		if (m_this_thread_hierarchy_value <= m_hierarchy_value) {
			throw std::logic_error("mutex hierarchy violated");
		}
	}
	/*请求到新的互斥元,更新当前互斥元的层级号为新的层级号,记录下当前层级号为历史(previous)层级号*/
	void update_hierarchy_value()
	{
		m_previous_hierarchy_value = m_this_thread_hierarchy_value;
		m_this_thread_hierarchy_value = m_hierarchy_value;
	}

public:
	// 创建互斥元对象的时候指定其所在的层级:m_hierarchy_value
	explicit HierarchicalMutex(unsigned long value):m_hierarchy_value(value),m_previous_hierarchy_value(0)
	{

	}

	// 加锁,更新层级号,更新前检查是否可请求
	void lock()
	{
		check_for_hierarchy_violation();
		m_mutex.lock();
		update_hierarchy_value();
	}

	void unlock() 
	{
		m_this_thread_hierarchy_value = m_previous_hierarchy_value;
		m_mutex.unlock();
	}

	bool try_lock()
	{
		check_for_hierarchy_violation();
		if (!m_mutex.try_lock())
			return false;
		update_hierarchy_value();
		return true;
	}
};
// 初始化为最大值,表示任意层级的互斥元(HierarchicalMutex对象)都可以被锁定
// thread_local作用: 每个线程都有属于关于m_this_thread_hierarchy_value的副本
// 在一个线程中该变量m_this_thread_hierarchy_value的状态完全独立于另外一个线程中
// 读取的该变量的状态
thread_local unsigned long HierarchicalMutex::m_this_thread_hierarchy_value(ULONG_MAX);


// 检查规则
// 刚开始m_this_thread_hierarchy_value的值为最大值:所以所有线程都可以绕过检查
// 线程1 创建并使用HierarchicalMutex对象对其某部分代码进行加锁,此时,指定其层级号为M
// 此时更新 m_this_thread_hierarchy_value=M
// 线程2 创建并使用HierarchicalMutex对象对其某部分代码进行加锁,此时,指定其层级号为N
// 若N<M
// 允许线程2进行加锁,执行代码
// 若N>=M
// 则线程2不允许使用HierarchicalMutex对象对其某部分代码进行加锁,程序抛出异常
// 只要若N<M的线程都允许进行资源的访问(这一点很重要!!!)
// 层级加锁的方式比 直接对资源进行std::mutex.lock()和std::mutex::unlock()的方式好
// 因为层级加锁允许多方修改(增删查看) 而std::mutex.lock()和std::mutex::unlock()只允许一个线程进行访问



// !!!!!!! 很重要
// 关于m_previous_hierarchy_value的说明
// 保存当前线程之前的层次有助于在unlock()时对其进行恢复
// 否则就无法再次锁定一个更高层次的互斥元(换句话说,就是无法使用更高层次的
// HierarchicalMutex对其想要加锁的代码进行互斥化访问)
// 直到m_this_thread_hierarchy_value的值变为ULONG_MAX,则说明所有加锁的线程都执行结束了


// try_lock的说明
// m_mutex调用try_lock失败:则无法拥有这个锁,就无法更新层次值,并返回false
// 原理和lock()函数相同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值