Windows 线程:什么时候应该使用 InterlockedExchangeAdd()?

发布于 2024-08-17 09:02:59 字数 781 浏览 5 评论 0原文

这个函数的命名看起来像是一些复杂的事情。人们到底什么时候知道这是正确的方法,而不是做这样的事情:

准备 CRITICAL_SECTION cs; int *p = malloc(sizeof(int)); // 分配站点 初始化CriticalSection(&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() 更有用?

The naming of this function seems like this is some complicated stuff going on. When exactly does one know that this is the way to go instead of doing something like this:

Preparation
CRITICAL_SECTION cs;
int *p = malloc(sizeof(int)); // Allocation Site
InitializeCriticalSection(&cs); // HINT for first Write

Thread #1
{
*p = 1; // First Write
}

Thread #2
{
EnterCriticalSection(&cs);
*p = 2; // Second Write
LeaveCriticalSection(&cs);
}

I have a write that gets done in one thread:

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

Then, I have a read that gets done in another thread (potentially at the same time):

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

What's the best solution to solve this race condition? Are critical sections the way to go or is the use of InterlockedExchangeAdd() more useful?

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

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

发布评论

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

评论(3

青朷 2024-08-24 09:02:59

就您而言,没有竞争条件。该变量永远不会重置回 FALSE,是吗?这只是线程的“请死”开关,对吧?那么就不需要任何类型的同步。

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

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

In your case, there's no race condition. The variable is never reset back to FALSE, is it? It's just a "please die" switch for the thread, right? Then no need for synchronization of any kind.

The InterlockedXXX family of functions makes use of Intel CPU's atomic 3-operand commands (XADD and CMPXCNG). So they're much cheaper than a critical section. And the one you want for thread-safe assignment is InterlockedCompareExchange().

UPD: and the mark the variable as volatile.

放血 2024-08-24 09:02:59

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::线程

InterlockedExchangeAdd is used to add a value to an integer as an atomic operation, meaning that you won't have to use a critical section. This also removes the risk of a deadlock if one of your threads throws an exception - you need to make sure that you don't keep any lock of any kind as that would prevent other threads from acquiring that lock.

For your scenario you can definitely use an Interlocked...- function, but I would use an event (CreateEvent, SetEvent, WaitForSingleObject), probably because I often find myself needing to wait for more than one object (you can wait for zero seconds in your scenario).

Upd: Using volatile for the variable may work, however it isn't recommended, see: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2016.html and http://www-949.ibm.com/software/rational/cafe/blogs/ccpp-parallel-multicore/tags/c%2B%2B0x for instance.

If you want to be portable, take a look at boost::thread.

铁憨憨 2024-08-24 09:02:59

确保 m_bIsTermminate 被标记为 volatile,这样就可以了。虽然对我来说这似乎很奇怪,但在将“已终止”设置为 true 后,您还要 // 更多代码。该变量到底表示什么?

您的“竞争条件”是 // more 代码的各个元素可以按不同的顺序执行。你的变量对此没有帮助。您的目标是让它们按确定的顺序执行吗?如果是,您需要一个条件变量来等待一个线程并在另一个线程中设置。如果您只是不想让它们同时执行,那么临界区就可以了。

Make sure m_bIsTerminated is marked as volatile, and you should be ok. Although it seems pretty weird to me that you'd // some more code after setting "is terminated" to true. What exactly does that variable indicate?

Your "race condition" is that your various elements of // more code can execute in different orders. Your variable doesn't help that. Is your goal to get them to execute in a deterministic order? If yes, you'd need a condition variable to wait on one thread and set in another. If you just don't want them executing concurrently, a critical section would be fine.

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