关于多线程操作同步对象造成死锁的解决方式(一)

7 篇文章 0 订阅
6 篇文章 0 订阅

        在多线程编程成中经常需要进行数据同步等操作,在临界区等对象使用时容易出现忘记退出临界区操作或中间执行的代码发生异常导致退出临界区代码未被正常执行,这个时候就很容易出现死锁现象了,那么我们这么解决上述问题呢? 

        这个问题解决的办法其实很简单,采用临时对象的方式去解决,也就是写一个自动锁的类,这个类用于接收一个临界区指针或引用,在构造时自动进入临界区,析构时自动退出临界区,那么我们也用关心是否遗漏退出临界区的代码或者被异常给终止了退出临界区的代码。


以下为实现:

SafetyAutoLock.h

/**
 *@class SafetyAutoLock
 *@brief 安全自动锁类,防止手动忘记释放临界区或异常导致临界区未释放
 *@author Flyound
 *@note 
 *必须采用栈方式使用,不允许跨代码段({...}/void func(){})
 */
class SafetyAutoLock
{
public:
	SafetyAutoLock(CRITICAL_SECTION * pCSLock);


	SafetyAutoLock(CRITICAL_SECTION * pCSLock, const char * szFile, const char * szFunc, long lLine);


	virtual ~SafetyAutoLock(void);
public:
	/**@brief 手动锁*/
	void Lock();


	/**@brief 手动释放锁,无需等待析构*/
	void UnLock();
	
	/**@brief 重新设置临界区*/
	void Reset(CRITICAL_SECTION * pCSLock);


	/**@brief 重新设置临界区*/
	void Reset(CRITICAL_SECTION * pCSLock, const char * szFile, const char * szFunc, long lLine);


	/**@brief 判断该锁是否有效(临界区指针是否正常)*/
	bool IsValid();
private:
	int				    			m_nLockCount;
	DWORD								m_dwCallStackID;
	CRITICAL_SECTION *  m_pCSLock;
};


SafetyAutoLock.cpp


SafetyAutoLock::SafetyAutoLock(CRITICAL_SECTION * pCSLock)
{
	m_nLockCount = 0;
	m_pCSLock    = pCSLock;

	Lock();
}


SafetyAutoLock::SafetyAutoLock(CRITICAL_SECTION * pCSLock, const char * szFile, const char * szFunc, long lLine)
{
	m_nLockCount = 0;
	m_pCSLock    = pCSLock;

	Lock();
}


SafetyAutoLock::~SafetyAutoLock(void)
{
	Reset(NULL);
}


void SafetyAutoLock::Lock()
{
	if (m_pCSLock)
	{
		m_nLockCount++;
		
		EnterCriticalSection(m_pCSLock);
	}
}


void SafetyAutoLock::UnLock()
{
	if (m_pCSLock && (--m_nLockCount) == 0)
	{
		LeaveCriticalSection(m_pCSLock);
	}
}

void SafetyAutoLock::Reset(CRITICAL_SECTION * pCSLock)
{
	while(m_nLockCount > 0)
	{
		UnLock();
	}
	
	m_nLockCount = 0;
	m_pCSLock    = pCSLock;


	Lock();
}

void SafetyAutoLock::Reset(CRITICAL_SECTION * pCSLock, const char * szFile, const char * szFunc, long lLine)
{
	if (pCSLock)
	{
		Reset(pCSLock);
	}
}


bool SafetyAutoLock::IsValid()
{
	return m_pCSLock != NULL;
}


上述代码能帮助我们规避因为粗心引起的死锁问题,那么下一篇将讲解如果监控死锁的发生,并能得知死锁发生的原因,快速定位死锁的代码并解决它。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值