简体   繁体   English

MFC ResumeThread 和 std::condition_variable 等待后偶尔线程同步失败

[英]Occassional thread sync fail after MFC ResumeThread and std::condition_variable wait

Background I am finishing up upgrading my MFC framework project from prototype to alpha production code.背景我正在完成将我的 MFC 框架项目从原型升级到 alpha 生产代码。 The task was to synchronize its threads.任务是同步它的线程。 I used a mixture of mutexes, condition variables and binary semaphores.我混合使用了互斥量、条件变量和二进制信号量。 This has been mostly successful.这基本上是成功的。 The stackoverflow case that most resembles my question is std::condition_variable wait() and notify_one() synchronization .与我的问题最相似的 stackoverflow 案例是std::condition_variable wait() and notify_one() synchronization

Problem Occasionally, though, an atomicity problem occurs after new'ing a certain class derived from CWinThread (RxWs2SocketThread).问题不过,有时,在新建从 CWinThread (RxWs2SocketThread) 派生的某个 class 之后会出现原子性问题。 RxWs2SocketThread switches to the new class'es thread and executes InitInstance and switches back again like it is supposed to. RxWs2SocketThread 切换到新类的线程并执行InitInstance并像预期的那样再次切换回来。 In single-threaded programs, when ResumeThread is called, the thread switch to InitInstance occurs without problem, but in my multithreaded program, I have to control the switching.在单线程程序中,调用ResumeThread时,线程切换到InitInstance没有问题,但在我的多线程程序中,我必须控制切换。 Here is the code:这是代码:

线程创建和实例化代码

The occasional fail occurs between line 95 and 102. Here is the app log showing a successful handoff:偶尔会在第 95 行和第 102 行之间发生失败。这是显示成功切换的应用程序日志:

成功条件 var 在 ResumeThread 之后等待

The number to the left is the thread number.左边的数字是线程号。 Line numbers are in brackets like [100].行号在方括号中,如 [100]。 Note that [100] is the instrumentation for the actual wait call on line 102. And this app log shows an example of where it fails:请注意,[100] 是第 102 行实际等待调用的检测。此应用程序日志显示了失败位置的示例:

条件变量等待不成功

In this log, the notify_one occurs before the wait , which causes the program to hang.在此日志中, notify_one发生wait之前,这导致程序挂起。 Note that line [100] in the app log, which represents the wait call in the code on line [102].请注意应用程序日志中的第 [100] 行,它代表第 [102] 行代码中的等待调用。

Question This tells me I need to provide atomicity between the ResumeThread and std::condition_variable.wait() calls.问题这告诉我需要在ResumeThreadstd::condition_variable.wait()调用之间提供原子性。 How can I do that?我怎样才能做到这一点? I have to resume the class thread, otherwise the InitInstance won't be called, but I can't do a wait after I resume the thread.我必须恢复class线程,否则不会调用InitInstance ,但是恢复线程后我不能等待。

It turns out the answer was right in front of me.原来答案就在眼前。 On code line 101, a lock is acquired on rxWs2SocketInitInstanceMu mutex.在代码行 101 上,在rxWs2SocketInitInstanceMu互斥量上获取了一个锁。 All I had to do was move the lock up to just before line 95 ResumeThread .我所要做的就是将锁移动到第 95 行ResumeThread之前。

Edit1: I switched out the std::condition_varialble synchronization primitive for future/promise . Edit1:我关闭了future/promisestd::condition_varialble同步原语。 The former requires the use of separate locking, which does work when the locking statement is put before the ResumeThread , but this leads to error-prone maintenance.前者需要使用单独的锁定,当锁定语句放在ResumeThread之前时,它会起作用,但这会导致容易出错的维护。 The future/promise primitive is designed to be one-off which is how it is used in my code. future/promise原语被设计为一次性的,这就是它在我的代码中的使用方式。

Note that the std::promise object is meant to be used only once (See cppreference)请注意,std::promise object 只能使用一次(参见 cppreference)

. .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM