Windows线程:何时应该使用InterlockedExchangeAdd()?

时间:2010-01-14 21:55:11

标签: c++ windows multithreading race-condition

这个函数的命名似乎是一些复杂的事情。当确切地知道这是要走的路而不是做这样的事情时:

制备     CRITICAL_SECTION cs;     int * p = malloc(sizeof(int)); //分配站点     InitializeCriticalSection(安培; CS); //提示第一次写

主题#1      {     * p = 1; //首先写     }

主题#2      {     EnterCriticalSection的(安培; CS);     * p = 2; //第二次写     LeaveCriticalSection(安培; CS);     }

我有一个写在一个线程中完成:

Run()
{
// some code
m_bIsTerminated = TRUE;
// some more code
}

然后,我有一个读取在另一个线程中完成(可能同时):

Terminate()
{
// some code
if( m_bIsTerminated )
{
m_dwThreadId = 0;
m_hThread = NULL;
m_evExit.SetEvent();
return;
}
// even more code
}

解决这种竞争条件的最佳解决方案是什么?关键部分是可行的,还是使用InterlockedExchangeAdd()更有用?

3 个答案:

答案 0 :(得分:3)

在你的情况下,没有竞争条件。该变量永远不会重置为FALSE,是吗?这只是线程的“请死”开关,对吗?然后不需要任何类型的同步。

InterlockedXXX系列函数使用Intel CPU的原子3操作数命令(XADD和CMPXCNG)。所以它们比关键部分便宜得多。你想要的线程安全分配是InterlockedCompareExchange()。

UPD:并将变量标记为易失性。

答案 1 :(得分:0)

确保将m_bIsTerminated标记为volatile,您应该没问题。虽然在将“终止”设置为true之后,你需要更多代码,这对我来说似乎很奇怪。该变量究竟表明了什么?

你的“竞争条件”是你的更多代码的各种元素可以以不同的顺序执行。你的变量没有帮助。您的目标是让他们以确定的顺序执行吗?如果是,您需要一个条件变量在一个线程上等待并在另一个线程中设置。如果您不希望它们同时执行,那么关键部分就可以了。

答案 2 :(得分:0)

InterlockedExchangeAdd用于将值作为原子操作添加到整数,这意味着您不必使用临界区。如果你的一个线程抛出异常,这也消除了死锁的风险 - 你需要确保不保留任何类型的锁,因为这会阻止其他线程获取该锁。

对于你的场景,你绝对可以使用一个Interlocked ...-函数,但我会使用一个事件(CreateEvent,SetEvent,WaitForSingleObject),可能是因为我经常发现自己需要等待多个对象(你可以等待)在你的场景中为零秒)。

更新:对变量使用volatile可能有效,但建议不要这样做,例如:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2016.htmlhttp://www-949.ibm.com/software/rational/cafe/blogs/ccpp-parallel-multicore/tags/c%2B%2B0x

如果您想要携带,请查看boost::thread