棘手的 InterlockedDecrement 与 CriticalSection

发布于 2024-11-28 00:36:18 字数 503 浏览 0 评论 0原文

有全局长计数计数器。
线程 A 执行

EnterCriticalSection(&crit);
// .... do something
count++;                       // (*1)
// .. do something else
LeaveCriticalSection(&crit);

线程 B 执行操作

InterlockedDecrement(&count); // (*2) not under critical secion.

在 (*1) 处,我处于临界区。在(*2),我不是。

如果没有 InterlockedIncrement() ,(*1) 安全吗? (它是受保护的关键部分)。
我需要在 (*1) 处使用 InterlockedIncrement() 吗?
我觉得我可以支持也可以反对。

There is global long count counter.
Thread A does

EnterCriticalSection(&crit);
// .... do something
count++;                       // (*1)
// .. do something else
LeaveCriticalSection(&crit);

Thread B does

InterlockedDecrement(&count); // (*2) not under critical secion.

At (*1), I am under a critical section. At (*2), I am not.

Is (*1) safe without InterlockedIncrement() ? (it is protected critical section).
Do I need InterlockedIncrement() at (*1) ?
I feel that I can argue both for and against.

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

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

发布评论

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

评论(3

凌乱心跳 2024-12-05 00:36:18

您应该使用其中一种,而不是混合使用它们。

虽然 InterlockedDecrement 保证是原子的,但operator++ 却不是,尽管在这种情况下它可能取决于您的体系结构。在这种情况下,您实际上根本没有保护 count 变量。

鉴于您似乎想要执行简单的递增/递减操作,我建议您在这种情况下只需删除关键部分并使用关联的 Interlocked* 函数。

You should use one or the other, not mix them.

While InterlockedDecrement is guaranteed to be atomic, operator++ is not, though in this case it likely will be depending upon your architecture. In this case, you're not actually protecting the count variable at all.

Given that you appear to want to do simple inrecrement/decrement operations, I would suggest that you simply remove the critical section in this case and use the associated Interlocked* functions.

北凤男飞 2024-12-05 00:36:18

两个线程都应使用任一 InterlockedDecrement/InterlockedIncrement同一临界区。混合和匹配没有理由正常工作。

考虑以下事件序列:

Thread A: enter the critical section
Thread A: read count into a register
Thread A: increment the value in the register
Thread B: InterlockedDecrement(&count) <<< There's nothing to stop this from happening!
Thread A: write the new count
Thread A: leave the critical section

最终结果:你丢失了一个减量!

关键部分的一个有用的(如果故意简化的话)心智模型是这样的:进入关键部分所做的就是阻止其他线程进入同一个临界区。它不会自动阻止其他线程执行可能需要同步的其他操作。

InterlockedDecrement 所做的一切就是确保递减的原子性。它不会阻止任何其他线程对变量的过时副本执行计算,然后将结果写回。

Both threads should use either InterlockedDecrement/InterlockedIncrement, or the same critical section. There is no reason for the mixing and matching to work correctly.

Consider the following sequence of events:

Thread A: enter the critical section
Thread A: read count into a register
Thread A: increment the value in the register
Thread B: InterlockedDecrement(&count) <<< There's nothing to stop this from happening!
Thread A: write the new count
Thread A: leave the critical section

Net result: you've lost a decrement!

A useful (if deliberately simplified) mental model for critical sections is this: all entering a critical section does is prevent other threads from entering the same critical section. It doesn't automatically prevent other threads from doing other things that may require synchronization.

And all InterlockedDecrement does is ensure the atomicity of the decrement. It doesn't prevent any other thread performing computations on an outdated copy of the variable, and then writing the result back.

离笑几人歌 2024-12-05 00:36:18

是的,你知道。

否则可能是:

  1. 读取值

  2. 该值以原子方式递增

  3. 原始值递增并写入,使之前的原子更新失效

。此外,两者都需要相同的关键部分,因为它无助于锁定单独的事物。 :)

Yes, you do.

Otherwise it could be that:

  1. The value is read

  2. The value is incremented atomically

  3. The original value is incremented and written, invalidating the previous atomic update

Furthermore, you need the same critical section for both, since it doesn't help to lock on separate things. :)

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