Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
原子操作C++; 在C++、Windows平台中,我想执行一组函数调用,以原子方式执行,这样就不会切换到进程中的其他线程。我该怎么做呢?有什么想法,提示吗_C++_Windows_Multithreading - Fatal编程技术网

原子操作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()

好吧,您可以暂停(使用)进程中的所有其他线程,但我认为您应该重新考虑程序的设计。

您不希望所有线程都等待,您只希望等待新线程完成,而不会错过信号的风险。这可以使用信号量来完成

使用CreateSemaphore(NULL,0,1,NULL)创建一个此代码和通过Restart最终执行的代码都知道的信号量。 在您展示的代码中,您仍将使用WaitforSingleObject来等待信号量。当执行发布代码的线程完成其工作时,让它调用ReleaseSemaphore

若首先调用ReleaseSamphore,WaitforSingleObject将允许您立即通过。如果首先调用WaitforSingleObject,它将等待ReleaseSamphore


也应该对您有所帮助。

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

您是否使用
PulseEvent()
来向您的句柄发送信号?如果是这样,那就是问题所在

根据,

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

因此,如果在等待句柄之前向其发出信号,则通过
PulseEvent()
将句柄立即置于未信号状态。这似乎就是你“错过”活动的原因。要更正此问题,请将
PulseEvent()
替换为
SetEvent()


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

尽管我担心您的设计总体上是有序的(即您将并发任务设置为连续的,因此失去了使其并发的所有辛苦工作的好处),但我认为我看到了简单的解决方案

将事件句柄更改为手动重置而不是自动重置。(请参见CreateEvent)

那你就不会错过信号了。 在WaitForSingleObject(…)之后,调用ResetEvent()

编辑:
忘了我刚才说的吧。那不行。请参阅下面的注释。

这很容易修复。只需确保事件是自动重置事件(请参阅CreateEvent的参数),并且只调用事件句柄的SetEvent,而不要调用ResetEvent或PulseEvent或其他一些东西。因此WaitForSingleObject将始终正确返回。如果已设置事件,WaitForSingleObject将立即返回并重置事件。

问题是:为什么要这样做?如果您试图通过禁止内核切换线程来“同步”访问数据结构,那么您的做法是非常错误的。所以请解释一下你为什么要这么做。即使你能做到这一点,它也会在一个多核系统上崩溃,这个系统会同时执行多个线程。你是如何给你的句柄发信号的
PulseEvent()
SetEvent()
?我用SetEvent()发出信号,这不会解决问题。如果他已经在使用一个自动重置事件,则该事件将一直保持信号状态,直到释放一个等待的线程。如果没有等待的线程,则事件将保持信号状态,直到有线程为止。此时,线程立即被释放,事件被重置。请参阅CreateEvent上的MSDN文档:哦,您的权利。我忘了。所以他一定是做错了什么。或者其他线程也在等待对象,或者他正在使用损坏的PulseEvent或其他东西。如果只需要通知一个线程,自动重置事件是非常可靠的。没有必要将自动重置事件更改为手动重置事件。许多人认为SuspendThread是不可靠的行为,他们认为只有调试器和垃圾收集器实现才应该挂起线程。