MFC ResumeThread 和 std::condition_variable 等待后偶尔线程同步失败
Posted
技术标签:
【中文标题】MFC ResumeThread 和 std::condition_variable 等待后偶尔线程同步失败【英文标题】:Occassional thread sync fail after MFC ResumeThread and std::condition_variable wait 【发布时间】:2021-09-02 09:31:08 【问题描述】:背景 我正在完成将我的 MFC 框架项目从原型升级到 alpha 生产代码。任务是同步其线程。我混合使用了互斥锁、条件变量和二进制信号量。这在很大程度上是成功的。与我的问题最相似的 *** 案例是 std::condition_variable wait() and notify_one() synchronization。
问题 但是,有时,在新建从 CWinThread (RxWs2SocketThread) 派生的某个类之后会出现原子性问题。 RxWs2SocketThread 切换到新类的线程并执行 InitInstance 并再次切换回来,就像它应该做的那样。在单线程程序中,当调用 ResumeThread 时,线程切换到 InitInstance 没有问题,但在我的多线程程序中,我必须控制切换。代码如下:
在第 95 行和第 102 行之间偶尔会发生失败。这是显示成功切换的应用日志:
左边的数字是线程号。行号在括号中,如 [100]。请注意,[100] 是第 102 行实际 wait 调用的检测工具。此应用程序日志显示了失败的示例:
在此日志中,notify_one 发生在 wait 之前,这会导致程序挂起。请注意应用日志中的第 [100] 行,它表示第 [102] 行代码中的 wait 调用。
问题 这告诉我我需要在 ResumeThread 和 std::condition_variable.wait() 调用之间提供原子性。我怎样才能做到这一点?我必须恢复类线程,否则不会调用InitInstance,但是恢复线程后我不能等待。
【问题讨论】:
【参考方案1】:原来答案就在我面前。
在代码行 101 上,在rxWs2SocketInitInstanceMu
mutex 上获得了一个锁。我所要做的就是将锁移到第 95 行之前ResumeThread
。
编辑1:
我为future/promise
切换了std::condition_varialble
同步原语。前者需要使用单独的锁定,当锁定语句放在ResumeThread
之前时确实有效,但这会导致容易出错的维护。 future/promise
原语被设计为一次性的,这就是它在我的代码中的使用方式。
请注意,std::promise 对象只能使用一次(参见 cppreference)
.
【讨论】:
以上是关于MFC ResumeThread 和 std::condition_variable 等待后偶尔线程同步失败的主要内容,如果未能解决你的问题,请参考以下文章
Windows API一日一练 50 SuspendThread和ResumeThread函数
为啥 -ansi 和 -std=c++11 在 g++ 中会发生冲突?
如何使用自动工具编译带有 clang 和选项 -std=c++11 的项目