一种简易有效的死锁诊断方法

死锁往往是概率性发生,多线程在特定时序下出现。难复现,多线程动态作用,此类问题排查往往很费劲。下面介绍一个简易的排查方法。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <map>
#include <set>
#include <sys/prctl.h>



using namespace std;

typedef struct _LOCK_TAG_INFO{
	const char* tags;
    int line;
	pthread_t pid;
	struct timeval  cur_time;
	char threadName[16];
    string str;
    pthread_mutex_t *pmutex;
    int flag;
}LOCK_TAG_INFO;

typedef struct _LOCK_MANGER{
	set<LOCK_TAG_INFO* > lockSet;		
	map<pthread_mutex_t *,LOCK_TAG_INFO > lockMap; 
	pthread_mutex_t 	lockMuetx;	
}LOCK_MANGER;

LOCK_MANGER g_lockManger;

pthread_mutex_t 	lockMuetx_1;	
pthread_mutex_t 	lockMuetx_2;

int m_mutex_lock(pthread_mutex_t *muet_t, const char *tag,int line)
{
	LOCK_TAG_INFO lockTagInfo;

	lockTagInfo.tags = tag;    
    lockTagInfo.line = line;
    lockTagInfo.pmutex = muet_t;
	gettimeofday(&lockTagInfo.cur_time, NULL);

	lockTagInfo.threadName[0] = 0;
	prctl(PR_GET_NAME,lockTagInfo.threadName);
	
	pthread_mutex_lock(&g_lockManger.lockMuetx);
	g_lockManger.lockSet.insert(&lockTagInfo);
	pthread_mutex_unlock(&g_lockManger.lockMuetx);
	
	pthread_mutex_lock(muet_t);

	pthread_mutex_lock(&g_lockManger.lockMuetx);
	g_lockManger.lockSet.erase(&lockTagInfo);
	gettimeofday(&lockTagInfo.cur_time, NULL);
	g_lockManger.lockMap[muet_t] = lockTagInfo;
	pthread_mutex_unlock(&g_lockManger.lockMuetx);
	return 0;
}


int m_mutex_unlock(pthread_mutex_t *muet_t)
{
	pthread_mutex_lock(&g_lockManger.lockMuetx);
	g_lockManger.lockMap.erase(muet_t);
	pthread_mutex_unlock(&g_lockManger.lockMuetx);
	
	pthread_mutex_unlock(muet_t);

	return 0;
}


int muteDump(void)
{
	LOCK_TAG_INFO *lockTagInfo = NULL;
	
	struct timeval  cur_time;
	
	gettimeofday(&cur_time, NULL);
	
	pthread_mutex_lock(&g_lockManger.lockMuetx);

	{
		std::set<LOCK_TAG_INFO*>::iterator iter;
		iter = g_lockManger.lockSet.begin();
	  	while(iter != g_lockManger.lockSet.end()){
			lockTagInfo = *iter;
            unsigned int t = (cur_time.tv_sec - lockTagInfo->cur_time.tv_sec)*1000 + (cur_time.tv_usec/1000 - lockTagInfo->cur_time.tv_usec/1000);
			printf("try p=%p t:%dsec-%dms pn:%s at:%s %d\n",lockTagInfo->pmutex,t/1000,t%1000,lockTagInfo->threadName,lockTagInfo->tags,lockTagInfo->line);
			iter++;
		}
	}
	
	{
		std::map<pthread_mutex_t *,LOCK_TAG_INFO >::iterator iter;
		iter = g_lockManger.lockMap.begin();
	  	while(iter != g_lockManger.lockMap.end()){
			if(pthread_mutex_trylock(iter->first) == 0){
				pthread_mutex_unlock(iter->first);
			}else{
				LOCK_TAG_INFO lockTagInfo = iter->second;
                unsigned int t = (cur_time.tv_sec - lockTagInfo.cur_time.tv_sec)*1000 + (cur_time.tv_usec/1000 - lockTagInfo.cur_time.tv_usec/1000);
			    printf("get p=%p t:%dsec-%dms pn:%s at:%s %d\n",lockTagInfo.pmutex,t/1000,t%1000,lockTagInfo.threadName,lockTagInfo.tags,lockTagInfo.line);
			}
			iter++;
		}
	}
	pthread_mutex_unlock(&g_lockManger.lockMuetx);
	return 0;
}

void* pthread_t1(void* p)
{
    prctl(PR_SET_NAME,"pthread_t1");
    while(1){
        m_mutex_lock(&lockMuetx_1,__FILE__,__LINE__);
        usleep(10*1000);
        m_mutex_lock(&lockMuetx_2,__FILE__,__LINE__);
        usleep(10*1000);
        m_mutex_unlock(&lockMuetx_2);
        m_mutex_unlock(&lockMuetx_1);
    }    
}
void* pthread_t2(void* p)
{
    prctl(PR_SET_NAME,"pthread_t2");
    while(1){
        m_mutex_lock(&lockMuetx_2,__FILE__,__LINE__);
        usleep(10*1000);
        m_mutex_lock(&lockMuetx_1,__FILE__,__LINE__);
        m_mutex_unlock(&lockMuetx_1);
        m_mutex_unlock(&lockMuetx_2);
    }    
}



int main()
{
    pthread_t phthread1,phthread2;
    pthread_create(&phthread1, NULL, pthread_t1, NULL);
    pthread_create(&phthread2, NULL, pthread_t2, NULL);   
    sleep(1);
    muteDump();
    return 0;

}

执行结果如下:

try p=0x55bff55010e0 t:0sec-990ms pn:pthread_t2 at:lockDumpDemo.cpp 133
try p=0x55bff5501120 t:0sec-990ms pn:pthread_t1 at:lockDumpDemo.cpp 121
get p=0x55bff55010e0 t:1sec-1ms pn:pthread_t1 at:lockDumpDemo.cpp 119
get p=0x55bff5501120 t:1sec-1ms pn:pthread_t2 at:lockDumpDemo.cpp 131

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值