原子操作C ++

时间:2009-11-05 12:59:21

标签: c++ windows multithreading

在C ++,Windows平台中,我想以原子的形式执行一组函数调用,以便执行不会切换到我的进程中的其他线程。我该怎么做呢?任何想法,提示?

编辑:我有一段代码:

someObject->Restart();

WaitForSingleObject(handle, INFINITE);

现在 Restart()函数异步工作,所以它会快速返回,当someObject重新启动时,它会从另一个线程向我发送一个事件,在那里我发信号通知事件句柄我就是等待,从而继续处理。但现在的问题是,在代码到达 WaitForSingleObject()部分之前,我收到重启完成事件并发出事件信号,之后 WaitForSingleObject()永远不会返回没有再发出信号。这就是为什么我要将 Restart() WaitForSingleObject()作为原子执行。

7 个答案:

答案 0 :(得分:9)

这通常是不可能的。您无法强制操作系统切换到其他线程 您可以做的是以下之一:

  • 使用锁,互斥锁,关键字部分或信号量来同步少数触及相同数据的线程。
  • 以win32 api调用的形式使用原子的基本操作,例如比较和交换或原子添加,例如InterlockedIncrement()InterlockedCompareExchange()

答案 1 :(得分:7)

您不希望所有线程都等待,您只想等待新线程完成,而不存在丢失信号的风险。这可以使用信号量来完成。

使用CreateSemaphore(NULL,0,1,NULL)创建此代码和最终由Restart执行的代码已知的信号量。 在你展示的代码中,你仍然会使用WaitforSingleObject来等待你的信号量。当执行Release代码的线程完成它的工作时,让它调用ReleaseSemaphore。

如果首先调用ReleaseSemaphore,WaitforSingleObject将允许您立即传递。如果首先调用WaitforSingleObject,它将等待ReleaseSemaphore。

MSDN也应该帮助你。

答案 2 :(得分:2)

丢失事件竞赛的一般解决方案是计数信号量。

答案 3 :(得分:1)

您是否使用PulseEvent()发出信号?如果是这样,那就是问题。

根据MSDN

  

如果没有线程在等待,或者没有   线程可以立即释放,   PulseEvent只是设置事件   对象的状态为无信号和   回报。

因此,如果在等待之前发出手柄信号,则手柄会立即被PulseEvent()置于无信号状态。这似乎是你“失踪”事件的原因。要更正此问题,请将PulseEvent()替换为SetEvent()

但是,在这种情况下,您可能需要在等待完成后重置事件。这当然取决于在应用程序的生命周期内是否多次执行此代码。假设您的等待线程是等待句柄的 线程,请使用CreateEvent()创建自动重置事件。这将在您等待线程释放后自动重置句柄,使其在下一次自动可用。

答案 4 :(得分:0)

好吧,你可以暂停(使用SuspendThread)流程中的所有其他线程,但我想你应该重新考虑你的程序设计。

答案 5 :(得分:0)

这很容易解决。只需确保事件是自动重置事件(请参阅CreateEvent的参数)并仅将SetEvent调用到事件句柄,从不调用ResetEvent或PulseEvent或其他一些事情。所以WaitForSingleObject将始终正确返回。如果事件已经设置,WaitForSingleObject将立即返回并重置事件。

答案 6 :(得分:-1)

虽然我一般都担心你的设计(即你正在使并发任务顺序完成,从而失去了努力使其并发的所有好处),但我认为我看到了简单的解决方案。

将事件句柄更改为MANUAL RESET而不是AUTORESET。 (参见CreateEvent)。

然后你不会错过这个信号。 在WaitForSingleObject(...)之后,调用ResetEvent()。

编辑: 忘了我刚说的话。那不行。见下面的评论。