我应该选择什么同步方案来避免实时 C++/MFC 应用程序上的死锁?

发布于 2024-12-08 08:51:32 字数 593 浏览 0 评论 0原文

我想问您一个问题,关于我应该选择哪种并发工具(CMutex、CSemaphore、CEvent)来使 C++/MFC 应用程序成为多线程。

它是一个实时的机器视觉应用程序,现在需要并发执行,并且需要从之前的单线程状态进行重构。

我的工作流程的一次迭代如下。我有 2 个生产者 A、B(MFC Workers),需要填充两个单独的数据结构(各 1 个)。第三个线程,消费者(也是 MFC Worker)被阻塞,直到 A 和 B 的两个数据都可用。然后,生产者 A 和 B 必须阻塞(每个线程在数据完成时),C必须醒来,执行计算,解锁 A 和 B 才能继续,然后再次阻塞,等待下一个段。

  1. 我不能使用队列(类似于 Actor)- 阻塞是一个要求 :(
  2. 我尝试了 CEvent 并且它有效。A、B 的 AutoResetEvents 可以解锁 CMultiLock 调用 C,然后从 C 调用 ManualResetEvent->Set(),以 解锁 A 和 B 等待后一个事件。我关心的是何时 重置此事件(例如,如果 A 错过整个 Set,然后重置。)
  3. 具有多个 2 的信号量是否可以代表更好的解决方案?

此致。

I would like to ask you a question regarding which concurrency facility (CMutex, CSemaphore, CEvent) should I choose, to make a C++/MFC, application multi-threaded.

It is a real time, machine vision application, that is required now to execute concurrently and it needs refactoring, from it's previous single-threaded status.

A single iteration of my workflow is the following. I have 2 producers A,B (MFC Workers) that need to fill two separate data structures (1 each). A third thread, a consumer (MFC Worker as well) is blocked, until both data become available from A and B. Then, producers A and B must block (each, upon their data completion), C must wake up, perform a calculation, unblock A and B to continue and become blocked again, waiting for the next segments.

  1. I must not use queues (Actor-like) - the blocking is a requirement
    :(
  2. I tried CEvent and it works. AutoResetEvents for A,B to unblock a
    CMultiLock call on C and then a ManualResetEvent->Set() from C, to
    unblock A and B waiting on the latter event. My concern is when to
    reset this event (in case e.g. A miss the whole Set and then Reset.)
  3. Do semaphores with plurality of 2 may stand for a better solution?

Best regards.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清醇 2024-12-15 08:51:32

C 必须等待两件事发生,因此最合乎逻辑的事情是它等待两个自动重置 CEvent 对象:一个由 A 设置,另一个由 B 设置。

当 C 完成后,A 和 B然后每个人都必须等待通知。由于有两个线程,并且都必须唤醒,因此很自然地会使用另一对自动重置 CEvent 对象,A 和 B 各一个。然后,C 可以在它被唤醒时设置这两个线程。完毕。

计数为 2 的信号量可用于唤醒 C --- C 等待两次,A 和 B 各自通知 --- 但这意味着 C 必须在第一次通知后唤醒才能等待第二次通知,这不太理想。

使用计数为 2 的信号量随后唤醒 A 和 B 可能会导致被盗唤醒和混乱。 C 向信号量发出两次信号。 A 醒来并获取信号,进行处理并通知 C,然后再次等待信号量。由于B还没有醒来,信号量仍然可用,所以A再次拿走它。同时 B 没有被卡住,因为它不会收到另一个信号,而 C 被卡住,因为它将等待 B 的下一个值。

另一种方法是使用 Windows 条件变量 API 而不是事件,但没有似乎是一个 MFC 包装器。请参阅 http://msdn.microsoft.com/en-我们/库/ms682052%28VS.85%29.aspx

C must wait for two things to happen, so the most logical thing is that it waits for two auto-reset CEvent objects: one set by A and one by B.

When C is done, A and B must each then wait for a notification. Since there are two threads, and both must wake up, the natural thing is to use another pair of auto-reset CEvent objects, one for each of A and B. C can then set both when it is done.

A semaphore with a count of 2 would work for waking C --- C waits twice, and each of A and B notify --- but this means that C must wake up after the first notification in order to wait for the second, which is less than ideal.

Using a semaphore with a count of 2 for waking A and B afterwards has the potential for stolen wake-ups and confusion. C signals the semaphore twice. A wakes and takes a signal, does its processing and notifies C, and then waits on the semaphore again. Since B hasn't yet woken up, the semaphore is still available, so A takes it again. Meanwhile B is not stuck, since it won't get another signal, and C is stuck, since it will wait for the next value from B.

An alternative is to use the Windows Condition Variable API rather than events, but there doesn't seem to be an MFC wrapper for that. See http://msdn.microsoft.com/en-us/library/ms682052%28VS.85%29.aspx

亽野灬性zι浪 2024-12-15 08:51:32

我会稍微修改你的选项 2 - 在两个事件上使用 CMultiLock 来阻止 C;然后使用另一事件来阻止A和B。C会设置两个个自动重置事件来唤醒A和B。然后你就不再有比赛了用于重置。

I would go for a slight modification of your option 2 - use a CMultiLock on two events to block C; then use another pair of events to block A and B. C would set two auto-reset events to wake up each of A and B. Then you no longer have the race for the reset.

屋顶上的小猫咪 2024-12-15 08:51:32

我提出了一个信号系统,使用由互斥锁保护的计数器。这将所有同步工作限制在一个不做其他事情的小类中。

A starts
A writes A-Data
A signals
A stops

B starts
B writes B-Data
B signals 
B stops

C starts
C reads A-Data and B-Data
C starts A, B
C stops


*Signal Class*

Mutex protected counter attribute

Receives signal for A, increment counter
Receives signal for B, increment counter
IF counter equals 2,  clear counter and start C

I propose a signalling system, using a counter protected by a mutex. This keeps all the synchronization work confined to one small class that does notheing else.

A starts
A writes A-Data
A signals
A stops

B starts
B writes B-Data
B signals 
B stops

C starts
C reads A-Data and B-Data
C starts A, B
C stops


*Signal Class*

Mutex protected counter attribute

Receives signal for A, increment counter
Receives signal for B, increment counter
IF counter equals 2,  clear counter and start C
扛刀软妹 2024-12-15 08:51:32

您可以简单地使用 CEvent 对象和 WaitForMultipleObjects(),它允许您通过第三个参数“bWaitAll”等待两个对象。

http://msdn.microsoft .com/en-us/library/windows/desktop/ms687025%28v=vs.85%29.aspx

You can simply use CEvent objects and than WaitForMultipleObjects() which allows you to wait on both objects via the third parameter 'bWaitAll'.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025%28v=vs.85%29.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文