我++线程安全

发布于 2024-10-31 03:42:32 字数 443 浏览 1 评论 0原文

这是对这个问题的补充,我可以得出结论,在 c/c++ 中,此类操作不是线程安全的。

我的问题是,就线程安全而言,我们需要在任何情况下获取吗?注意这里锁是一个逻辑概念,即使你使用 InterlockedIncrement() 或 c++0x 原子类型,锁在概念上也是通过使用 cmpxchg 来获取的。

例如,如果只有一个写线程和多个读线程,那么读线程会得到奇怪的值吗?我假设

  1. 类型 i 在 x86 平台上是 32 位,在 x64 平台上是 64 位。
  2. 旧值或新值都可以。

It is the addition to this question, I can conclude that in c/c++, such operation isn't thread-safe.

my question is need we acquire lock in any case in terms of thread-safety? note here lock is a logical concept, even if you use InterlockedIncrement() or c++0x atomic type, lock is acquired conceptually by using cmpxchg.

For example, if there are only one-write-thread and many-read-threads, can read-thread get strange value? I assume

  1. The type i is 32-bit on x86 platform or 64-bit on x64 platform.
  2. Either old value or new value is OK.

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

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

发布评论

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

评论(2

甜`诱少女 2024-11-07 03:42:32

对于单个值的单个写入者和多个读取者来说,它是线程安全的,但在一般情况下,此类操作不是线程安全的(因此需要锁或使用原子操作) 。此外,线程安全的含义在这里非常有限。

如果您只是在一个线程中执行 i++ ,其他线程将看到旧值或新值。在您提到的两个平台上,这些值是原子存储/加载的,因此它们无法获得一半的值。然而,一般情况下情况并非如此,例如 x86 上的 64 位值将不是原子的,因此读者可以获得旧值的一半和新值的一半。所以这里的线程安全是非常特定于平台的。

不过你还是要小心。如果这是一个普通的int,优化器可能会简单地丢弃加载操作(也许在寄存器中保留一个副本)。在这种情况下,读者将永远不会获得新的值。如果您要循环执行此操作,这一点至关重要。不幸的是,执行此操作的唯一标准正确方法是使用 C++0x 使用 atomic 类型(易失性 现在对于某些编译器来说可以达到此目的)。

如果您确实添加了第二个编写器,那么增量运算符当然根本不是线程安全的。但是,您可以在这里使用原子添加函数,这将使其再次成为线程安全的。

In the case of a single writer and many-readers to this single value it is thread-safe, but in the general case such operations are not thread-safe (thus needing a lock or using atomic operations). Also, what thread-safe means is very limited here.

If you simply do i++ in one thread, the other threads will either see the old value or the new value. On the two platforms you mention the values are atomically stored/loaded, so they cannot get half a value. This is however not true in general, for example a 64-bit value on x86 will not be atomic, so the reader could get half of the old value and half of the new value. So thread-safety here is very platform specific.

You still have to be careful however. If this is a plain int the optimizer may simply discard the load operation (perhaps keep a copy in a register). In this case the reader will never get a new value. This is vital if you are doing this in a loop. Unfortunately the only standards correct way of doing this is with C++0x using an atomic<T> type (volatile kind of serves this purpose now for some compilers).

If you do add a second writer the increment operator is of course not thread-safe at all. You could however here use an atomic add function which would make it thread safe again.

狼亦尘 2024-11-07 03:42:32

如果您有权访问 Qt,请查看他们的 QAtomicInt 类。它是完全独立的,可以(我设法做到了)从那里提取所有必要的东西来拥有一个独立的可移植的atomic_int类。

它提供具有屏障语义的原子 fetch_and_storefetch_and_addcompare_and_swapincrementdecrement (获取、释放、完全、无屏障),尽管在 x86 上每个操作都将是完全屏障。

还有一个 QAtomicPointer 类模板。

If you have access to Qt, check out their QAtomicInt class. It is quite self contained, it is possible (I managed to do it) to pull all the necessary stuff from there to have a standalone portable atomic_int class.

It provides atomic fetch_and_store, fetch_and_add, compare_and_swap, increment and decrement with barrier semantics (acquire, release, full, no barrier), although on x86 every operation will be full barrier.

There is a QAtomicPointer class template too.

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