C++获取互斥锁的占有者

本文探讨了如何在C++中判断一个进程是否死锁,主要涉及通过资源分配图来分析死锁状态。由于C++中没有直接API获取互斥锁的占有者,作者提出了通过继承和组合现有类的方法来实现这一功能,以避免因析构函数非虚而导致的问题,并给出了测试代码示例,以帮助进行死锁分析和预防。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在刷面经的时候经常能看到诸如一个进程如何判断另外一个进程是否死锁的问题?然后各种百度,得到答案主要有两种,一种是通过查看线程栈帧是否一直wait在某个地方,另外一种是通过对所有的锁资源建立资源分配图,如下图:

图中箭头指向P代表P已经获取到该资源,而箭头指向R代表R真在被申请。在这张图中就是

P1:获取到两个R1,申请一个R2

P2:获取到一个R1,申请一个R2

当前并没出现死锁,因为R2的资源足够分配给P1,P1处理完退回R1,则P2能够获取到所有的资源并去处理。

但是假如R2只有一个,则P1无法申请到R2,从而无法退回R1,则会导致P2也申请不到R1,进而互相等待,即死锁。

在这个地方我们首先需要考虑的解决问题,是在某个检测线程中能够获取到所有资源的分配情况。但是这个问题我也是找了很久的api,始终没找到能获取到某个mutex被占有的情况。

所以我想了一个思路就是通过继承拓展已有的类资源,这样重写方法没那么多,这个方法在java里面应该没什么问题,但是在C++里面,因为mutex继承自_Mutex_base,而_Mutex_base的析构方法并不是虚的,这样就会导致一些问题,比如我们的继承类的析构函数可能会执行不到,从而导致内存泄漏。所以这里我们在用组合的方式进行。

这里有个简单的参考实现

class MyMutex {
public:
	bool locked = false;
	decltype(this_thread::get_id()) id;
	mutex m;
	void lock() {
		m.lock();
		cout << "thread :" << this_thread::get_id() <<" --> lock" << endl;
		id = this_thread::get_id();
		locked = true;
	}

	void unlock() {
		if (id == this_thread::get_id()) {
			cout << "thread :" << this_thread::get_id() << " --> unlock" << endl;
			id = thread::id();
			locked = false;
			m.unlock();
		}
	}

	auto lockThread()->decltype(auto) {
		return id;
	}
};

测试代码:

int main() {
	MyMutex m;
	vector<thread> p;
	m.lock();
	m.unlock();
	unique_lock ul{m};
	
	for (int i = 0; i < 4;i++) {
		p.push_back(thread{ [&m] {
			Sleep(500);
			cout << "childe m:" << this_thread::get_id() << endl;
			{
				lock_guard<MyMutex> lg{ m };
			}
		} });
	}
	ul.unlock();
	cout << "main:" << this_thread::get_id() << endl;

	while (true) {
		cout <<"main m:"<< m.lockThread() << endl;
		Sleep(1000);
	}
	return 0;
}

 

输出结果:

通过这样我们就能简单的实现锁资源的占有情况进行分析,从而能够建立资源分配图来进行程序内的死锁分析,进而进行死锁解除操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值