WaitForSingleObject 死锁

Posted

技术标签:

【中文标题】WaitForSingleObject 死锁【英文标题】:WaitForSingleObject Deadlock 【发布时间】:2015-11-05 17:32:13 【问题描述】:

如果你有兴趣,一些背景知识,否则你可以直接进入底部的问题:

我遇到了一个问题,我有一个无限的while 循环,其中两个if 条件检查两个事件对象状态是否变为信号状态。

while(1)

    if(DAQ_Comm_Server::usb_detect_flag == false)
    
        if(WaitForSingleObject(USB_PHY_CONN,INFINITE) == WAIT_OBJECT_0)
        
            DAQ_Comm_Server::usb_detect_flag = true;
        
    

    if(DAQ_Comm_Server::usb_detect_flag == true)
    
        if(WaitForSingleObject(USB_PHY_DISCONN, INFINITE) == NULL)
        
            DAQ_Comm_Server::usb_detect_flag = false;
           
    

事件对象 USB_PHY_CONNUSB_PHY_DISCONN 正在我的 OS/BSP USB 驱动程序代码中设置,它将检测硬件 USB 连接并继续使用 SetEvent() 设置相应的事件对象。

阅读WaitForSingleObject() 的文档,它并没有明确声明它必须在线程内使用,尽管在多次阅读后我觉得它是隐含的,但我不是 100% 确定。

我遇到的问题是代码第一次通过 while 循环运行(即,usb 最初断开连接,然后连接,然后断开连接),我的系统运行正常并且没有挂起。但是,重新连接 USB 后,我的系统冻结了。我的设备变得无响应/UI 冻结并且代码丢失。

现在,当我终止包含上述代码的进程时,一切都会重新启动并继续正常运行。我做了一些阅读,似乎WaitForSingleObject() 有可能出现死锁的风险,但我也注意到它总是在线程方面。

我的问题是WaitForSingleObject() 必须在线程中使用吗?如果我在主程序的无限循环中使用它,这是否会导致死锁/系统冻结的高风险?

注意:这是一个带有 VS2008 的平台构建器 windows Embedded CE 7 项目。

【问题讨论】:

如果您在 UI 线程上使用 WaitForSingleObject,则消息处理将停止,系统可能会将您的窗口视为无响应。请查看MsgWaitForMultipleObjects 如果您只有来自main 的线程,那么它在逻辑上也必须是您的 UI 线程。 (Windows 允许你使用 any 线程作为 UI 线程,不需要是 main 线程。如果你喜欢危险的生活,你甚至可以有一个 UI 线程 per窗口 !) @MSalters 我的 UI 线程在另一个进程中。 @Javia1492:我很确定您的 UI 线程不是在另一个进程中。 Windows 不允许这样做。根据定义,窗口的 UI 线程是创建窗口的线程。如果它是你的窗口(即你的进程创建并控制它),那么它的UI线程就是你进程中的一个线程。 【参考方案1】:

你不能在线程之外执行代码!有一个从 main 开始的“主”线程,但这也是一个和其他线程一样的线程。

也就是说,死锁需要 2 个线程和 2 个同步点。一个线程锁定 A,另一个线程锁定 B,然后两个线程在尝试获取另一个锁定时都阻塞。

这完全可以通过锁定命令来解决。如果锁 A总是在 B 之前被锁定,那么拥有 A 的线程与拥有锁 B 的其他线程之间不会发生死锁。

更理论的方法证明问题是锁图中的循环。循环 AB 是长度为 2 的最简单循环。 A->B->C->A 也可以死锁。锁顺序的有向无环图对应于无死锁程序。

【讨论】:

和往常一样,Don't forget to include the message queue in your lock hierarchy。 好的,所以我没有意识到我的 main 也可以用作线程。 @Javia1492:主线程不作为线程"function"。它thread。你永远不能在线程之外运行代码。 @MSalters 谢谢你的解释。这回答了我的问题,也帮助我缩小了具体问题的范围。

以上是关于WaitForSingleObject 死锁的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 死锁

WaitForSingleObject 与联锁*

WaitForSingleObject 不会超时

WaitForSingleObject 和 WaitForMultipleObjects函数

CreateProcess .. WaitForSingleObject .. CloseHandle 调用的最佳 try..finally 位置

WaitForSingleObject 和事件,行为不明确