zoukankan      html  css  js  c++  java
  • Windbg调试互斥体(Mutex)死锁

    一. 测试代码

    #include <windows.h>
    #include <tchar.h>
    #include <process.h>
    
    HANDLE hMutexA = NULL;
    HANDLE hMutexB = NULL;
    
    unsigned __stdcall ThreadProc1(void * pArg) {
    	WaitForSingleObject(hMutexA, INFINITE);
    	Sleep(500);
    	WaitForSingleObject(hMutexB, INFINITE);
    
    	printf("+++
    ");
    
    	ReleaseMutex(hMutexB);
    	ReleaseMutex(hMutexA);
    
    	return 0;
    }
    
    unsigned __stdcall ThreadProc2(void * pArg) {
    	WaitForSingleObject(hMutexB, INFINITE);
    	Sleep(500);
    	WaitForSingleObject(hMutexA, INFINITE);
    
    	printf("...
    ");
    
    	ReleaseMutex(hMutexA);
    	ReleaseMutex(hMutexB);
    
    	return 0;
    }
    
    int main()
    {
    	hMutexA = CreateMutex(NULL, FALSE, TEXT("MutexA"));
    	hMutexB = CreateMutex(NULL, FALSE, TEXT("MutexB"));
    
    	// 启动线程
    	HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc1, NULL, 0, NULL);
    	HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc2, NULL, 0, NULL);
    
    
    	getchar();
    
    	// 等待线程退出并关闭句柄
    	if (hThread1) {
    		WaitForSingleObject(hThread1, INFINITE);
    		CloseHandle(hThread1);
    	}
    
    	if (hThread2) {
    		WaitForSingleObject(hThread2, INFINITE);
    		CloseHandle(hThread2);
    	}
    
    	// 关闭句柄
    	if(hMutexA)
    		CloseHandle(hMutexA);
    	if(hMutexB)
    		CloseHandle(hMutexB);
    
        return 0;
    }
    

    二. 死锁原理

    程序生成了2个线程(线程1、线程2)和2个互斥体MutexA和MutexB。
    观察线程执行代码可知,这是一个典型的死锁用例,2个线程相互等待。

    线程1: 拥有MutexA --> 过一段时间(sleep) ---> 想拥有MutexB

    线程2: 拥有MutexB --> 过一段时间(sleep) ---> 想拥有MutexA

    线程1想拥有属于线程2的MutexB,而线程2却想拥有属于线程1的MutexA,互不松手,就只能都等着了。

    三. 上调试器

    ~*kvn 查看所有线程调用堆栈:

    从线程#1栈帧03可以看到其正在等待句柄00000038。
    从线程#2栈帧03可以看到其正在等待句柄00000034。
    即:
    线程#1(ID:22f4)--->等待句柄38
    线程#2(ID:33bc)---> 等待句柄34

    到底句柄00000034和00000038是什么类型的,可以使用!handle命令查看:

    从图中可以看到:
    句柄00000034为名为MutexA的互斥体,被线程ID:2264 拥有。
    句柄00000038为名为MutexB的互斥体,被线程ID:33bc 拥有。

    即:
    线程#1(ID:22f4)等待00000038(互斥体MutexA ),拥有00000034(互斥体MutexB)
    线程#2(ID:33bc)等待句柄00000034(互斥体MutexB ),拥有00000038(互斥体MutexA)

    所以,爱就是放手,有时候放手会让彼此过得更好。

  • 相关阅读:
    vue登录注册及token验证
    react实现登录注册
    React Native仿京东客户端实现(首页 分类 发现 购物车 我的)五个Tab导航页面
    进度条效果
    手风琴切换效果
    React实现了一个鼠标移入的菜单栏效果
    react购物车
    react实现tab切换效果
    网络缓存
    java线程面试手写题
  • 原文地址:https://www.cnblogs.com/jiangxueqiao/p/7418074.html
Copyright © 2011-2022 走看看