msdn对SuspendThread 的说明:

This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread. To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately.

虽然大家都知道尽量不要在外面调用 SuspendThread 暂停线程,不要用 TerminateThread 结束线程,但是都停留在感性认识阶段,这里给出了一段示例代码,看看 SuspendThread 造成死锁的情况。

UINT AFX_CDECL ThreadTest(LPVOID pvParam) { while (TRUE) { HMODULE hHandle = ::LoadLibrary("Common.dll"); if (hHandle) { void *pFun = (void *)::GetProcAddress(hHandle, "doSomething"); ::FreeLibrary(hHandle); } ::Sleep(10); } } void CTESTWIN2Dlg::OnOK() { CWinThread *pThread = AfxBeginThread(ThreadTest, (LPVOID)this, 0, 0, CREATE_SUSPENDED); ::DuplicateHandle(::GetCurrentProcess(), pThread->m_hThread, ::GetCurrentProcess(), &m_hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); pThread->ResumeThread(); m_bIsRun = TRUE; SetTimer(10, 10, NULL); } void CTESTWIN2Dlg::OnTimer(UINT nIDEvent) { if (m_bIsRun) { ::SuspendThread(m_hThread); m_bIsRun = FALSE; HMODULE hHandle = ::LoadLibrary("TSVul.dat"); if (hHandle) { void *pFun = (void *)::GetProcAddress(hHandle, "MyDoSome"); ::FreeLibrary(hHandle); } } else { ::ResumeThread(m_hThread); m_bIsRun = TRUE; } CDialog::OnTimer(nIDEvent); } UINT AFX_CDECL ThreadTest(LPVOID pvParam) { while (TRUE) { HMODULE hHandle = ::LoadLibrary("Common.dll"); if (hHandle) { void *pFun = (void *)::GetProcAddress(hHandle, "doSomething"); ::FreeLibrary(hHandle); } ::Sleep(10); } } void CTESTWIN2Dlg::OnOK() { CWinThread *pThread = AfxBeginThread(ThreadTest, (LPVOID)this, 0, 0, CREATE_SUSPENDED); ::DuplicateHandle(::GetCurrentProcess(), pThread->m_hThread, ::GetCurrentProcess(), &m_hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); pThread->ResumeThread(); m_bIsRun = TRUE; SetTimer(10, 10, NULL); } void CTESTWIN2Dlg::OnTimer(UINT nIDEvent) { if (m_bIsRun) { ::SuspendThread(m_hThread); m_bIsRun = FALSE; HMODULE hHandle = ::LoadLibrary("TSVul.dat"); if (hHandle) { void *pFun = (void *)::GetProcAddress(hHandle, "MyDoSome"); ::FreeLibrary(hHandle); } } else { ::ResumeThread(m_hThread); m_bIsRun = TRUE; } CDialog::OnTimer(nIDEvent); }

win32下的API基本都是线程安全的,因此API里面有很多线程同步的地方,LoadLibrary里面有一个临界区,线程函数在执行到LoadLibrary里面之后,如果刚好走到LoadLibrary的临界区里面,此时主线程的ontimer触发,将该线程挂起,ontimer继续执行,运行到LoadLibrary后,由于线程中LoadLibrary还没有从临界区出来,此时就造成主线程ontimer里面的LoadLibrary无限等待,主线程挂起。

因此不建议用suspend暂停线程,MSDN也有说明,suspend最好只在debug里面使用。

那怎么使线程挂起呢?可以使用事件等方式,用wait族函数来暂停线程

SuspendThread 造成程序死锁的一个例子相关推荐

  1. 使用JDK自带的工具jstack找出造成运行程序死锁的原因

    Java多线程编程也是Java面试中经常考察的内容.刚接触Java多线程编程的朋友们,可能会不慎写出一些会导致死锁(deadlock)的应用出来.如何分析造成Java多线程的原因呢?很多时候我们在怀疑 ...

  2. php+我的第一个程序,2. 第一个 C 程序

    首先请看下面这个简单的 C 程序,猜猜它会做些什么.猜不出来也没关系,后面会有详细的解说. #include int main( void )            /* 一个简单的程序 */     ...

  3. 用一个例子告诉你gdb调试工具如何使用

                                        用GDB调试程序 GDB概述 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式 ...

  4. win32 实现死锁的小例子

    死锁的一种情况是两个线程竞争两个锁,需要同时拿到两个锁才能执行,然后出现了两个线程各拿一个锁的情况,这样两个线程就都无法继续执行,称为死锁. 避免死锁的方法有很多,有预防死锁,出现死锁后通过某些方法释 ...

  5. Angular component的一个例子

    官网:https://angular.io/guide/architecture-components Before a view is displayed, Angular evaluates th ...

  6. 通过一个例子介绍 IDA pro 的简单使用

    From:通过一个例子介绍IDA pro的简单使用 - 知乎 IDA pro 7.6 绿色便携版:http://www.ddooo.com/softdown/215615.htm 配置IDA使用Ana ...

  7. SDN精华问答 | 使用SDN的一个例子

    SDN火热了好一阵子,无论运营商.政府企业.投资机构,一段时间,不知道SDN.不能甩几个SDN相关的名词术语,似乎都落后于时代了.今天,就来看看关于SDN的精华问答吧. 1 Q:为什么会出现SDN呢? ...

  8. 《游戏设计师修炼之道:数据驱动的游戏设计》一2.3 创建漏洞:一个例子

    2.3 创建漏洞:一个例子 现在,让我们使用上文提到的所有项目设计一个场景,通过实际演练来了解善意程序造成的恶劣后果.本章开始提到的电子邮件程序就是个好例子.稍后,我们将按照SDLC的所有步骤,来看看 ...

  9. CodeProject - 在C#使用SHGetFileInfo获取(管理)文件或者文件夹图标(C#封装Win32函数的一个例子)...

    Obtaining (and managing) file and folder icons using SHGetFileInfo in C# 作者:Paul Ingles  翻译:小新0574 审 ...

最新文章

  1. JS中的!=、== 、!==、===的用法和区别。
  2. 第二届团体程序设计天梯赛
  3. 如何用python创建一个下载网站-详解如何用python实现一个简单下载器的服务端和客户端...
  4. DL之DNN:基于Tensorflow框架对神经网络算法进行参数初始化的常用九大函数及其使用案例
  5. 创业新力量缔造新未来,岳麓峰会再增“长沙势能”
  6. vc 中C 语言命名规范(转)
  7. matlab求刚度,matlab直接刚度法计算结构频率
  8. json数据格式分析
  9. 固高控制卡学习(vs2010,c++)(之一)
  10. php写幻灯片,JavaScript原生代码实现幻灯片
  11. 首个集成BNB应用侧链链游Meta Apes,必看全新测评与攻略
  12. rap韵脚大全(包含各种诗词歌曲的韵脚等)
  13. postgres 退出_Postgresl选择正确的关闭模式
  14. 写给父亲的语音计算器(‘(‘‘)‘括号优先级处理递归算法c#,一)
  15. 作业5 | AR模型参数的估计
  16. 音乐app用户推荐系统构建_一款专门给用户推荐动听音乐的音乐期刊类的应用。画面极简优美...
  17. XSLT-FO基础知识
  18. Hive 数据聚合成键值对时,根据值大小进行排序
  19. 2014-1-28 思杨的咒语“胖乎乎真好看”
  20. python画图小猪佩奇_python 画个小猪佩奇

热门文章

  1. matlab提取FY4数据CLM
  2. IGBT驱动及保护电路(之一)
  3. 【承】Redis 原理篇——Redis 高性能深入剖析
  4. Vue solt 插槽使用~
  5. modbus的寄存器的地址
  6. 【STM32】 DMA原理,步骤超细详解,一文看懂DMA
  7. android nand 空间,2020年主流智能手机,内置NAND闪存平均容量100GB
  8. XLM解读(论文 + PyTorch源码)
  9. 广州大学大学物理练习1 质点运动学
  10. JpaTransactionManager的初始化和获取事务