i ++线程安全

时间:2011-04-08 06:08:14

标签: c++ c multithreading

这是this question的补充,我可以得出结论,在c / c ++中,这样的操作不是线程安全的。

我的问题是我们是否需要在线程安全方面获得任何情况 锁定?注意这里lock是一个逻辑概念,即使你使用InterlockedIncrement()或c ++ 0x原子类型,也可以通过 cmpxchg 从概念上获取锁。

例如,如果只有一个写线程和多个读线程,可以读取线程获得奇怪的值吗?我假设

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

2 个答案:

答案 0 :(得分:4)

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

如果您只是在一个线程中执行i++,则其他线程将查看旧值或新值。在你提到的两个平台上,值是以原子方式存储/加载的,因此它们不能获得一半的值。然而,这通常是不正确的,例如x86上的64位值不是原子的,因此读者可以获得旧值的一半和新值的一半。所以 thread-safety 在这里是非常特定于平台的。

但是你还是要小心。如果这是普通的int,优化器可能只是放弃加载操作(可能在寄存器中保留一份副本)。在这种情况下,读者永远不会得到新的价值。如果你在循环中这样做,这是至关重要的。不幸的是,唯一标准的正确方法是使用atomic<T>类型的C ++ 0x( volatile 类型现在为某些编译器服务)。

如果你确实添加了第二个编写器,增量运算符当然不是线程安全的。但是,您可以使用原子添加功能,使其再次成为线程安全。

答案 1 :(得分:0)

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

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

也有QAtomicPointer类模板。