原子操作C++; 在C++、Windows平台中,我想执行一组函数调用,以原子方式执行,这样就不会切换到进程中的其他线程。我该怎么做呢?有什么想法,提示吗
编辑:我有一段代码如下:原子操作C++; 在C++、Windows平台中,我想执行一组函数调用,以原子方式执行,这样就不会切换到进程中的其他线程。我该怎么做呢?有什么想法,提示吗,c++,windows,multithreading,C++,Windows,Multithreading,编辑:我有一段代码如下: someObject->Restart(); WaitForSingleObject(handle, INFINITE); 现在,Restart()函数异步执行其工作,因此它会快速返回,当someObject重新启动时,它会从另一个线程向我发送一个事件,我在该线程中向等待的事件句柄发送信号,从而继续处理。但现在的问题是,在代码到达WaitForSingleObject()部分之前,我收到重新启动完成事件并向该事件发送信号,然后WaitForSingleObje
someObject->Restart();
WaitForSingleObject(handle, INFINITE);
现在,Restart()函数异步执行其工作,因此它会快速返回,当someObject重新启动时,它会从另一个线程向我发送一个事件,我在该线程中向等待的事件句柄发送信号,从而继续处理。但现在的问题是,在代码到达WaitForSingleObject()部分之前,我收到重新启动完成事件并向该事件发送信号,然后WaitForSingleObject()再也不会返回,因为它不再发送信号。这就是为什么我希望将Restart()和WaitForSingleObject()作为原子执行。这通常是不可能的。您不能强制操作系统不切换到其他线程。
您可以执行以下操作之一:
- 使用锁、互斥锁、关键部分或信号量来同步几个接触相同数据的线程
- 使用原子的基本操作,如比较和交换,或以win32 api调用的形式使用原子添加,如
和InterlockedIncrement()
InterlockedCompareExchange()
也应该对您有所帮助。丢失事件竞赛的一般解决方案是计数信号量。您是否使用
PulseEvent()
来向您的句柄发送信号?如果是这样,那就是问题所在
根据,
如果没有线程在等待,或者如果没有
线程可以立即释放,
PulseEvent只是设置事件
对象的状态设置为非信号状态,并且
返回
因此,如果在等待句柄之前向其发出信号,则通过PulseEvent()
将句柄立即置于未信号状态。这似乎就是你“错过”活动的原因。要更正此问题,请将PulseEvent()
替换为SetEvent()
但是,在这种情况下,您可能需要在等待完成后重置事件。当然,这取决于此代码在应用程序的生命周期中是否多次执行。假设等待线程是等待句柄的唯一线程,请使用
CreateEvent()
创建自动重置事件。这将在释放等待的线程后自动重置句柄,使其在下一次通过时自动可用。尽管我担心您的设计总体上是有序的(即您将并发任务设置为连续的,因此失去了使其并发的所有辛苦工作的好处),但我认为我看到了简单的解决方案
将事件句柄更改为手动重置而不是自动重置。(请参见CreateEvent)
那你就不会错过信号了。
在WaitForSingleObject(…)之后,调用ResetEvent()
编辑:
忘了我刚才说的吧。那不行。请参阅下面的注释。这很容易修复。只需确保事件是自动重置事件(请参阅CreateEvent的参数),并且只调用事件句柄的SetEvent,而不要调用ResetEvent或PulseEvent或其他一些东西。因此WaitForSingleObject将始终正确返回。如果已设置事件,WaitForSingleObject将立即返回并重置事件。问题是:为什么要这样做?如果您试图通过禁止内核切换线程来“同步”访问数据结构,那么您的做法是非常错误的。所以请解释一下你为什么要这么做。即使你能做到这一点,它也会在一个多核系统上崩溃,这个系统会同时执行多个线程。你是如何给你的句柄发信号的
PulseEvent()
或SetEvent()
?我用SetEvent()发出信号,这不会解决问题。如果他已经在使用一个自动重置事件,则该事件将一直保持信号状态,直到释放一个等待的线程。如果没有等待的线程,则事件将保持信号状态,直到有线程为止。此时,线程立即被释放,事件被重置。请参阅CreateEvent上的MSDN文档:哦,您的权利。我忘了。所以他一定是做错了什么。或者其他线程也在等待对象,或者他正在使用损坏的PulseEvent或其他东西。如果只需要通知一个线程,自动重置事件是非常可靠的。没有必要将自动重置事件更改为手动重置事件。许多人认为SuspendThread是不可靠的行为,他们认为只有调试器和垃圾收集器实现才应该挂起线程。