【问题标题】:Using volatile long as an atomic使用 volatile long 作为原子
【发布时间】:2010-06-26 01:48:50
【问题描述】:

如果我有这样的事情......

volatile long something_global = 0;

long some_public_func()
{
    return something_global++;
}

当使用多个线程访问时,期望此代码不会中断(竞争条件)是否合理?如果它不是标准的,是否仍然可以作为对现代编译器的合理假设?

注意:我使用它的只是原子增量和减量 - 没有什么更高级的了。

【问题讨论】:

    标签: c++ c multithreading concurrency atomic


    【解决方案1】:

    否 - 易失性并不意味着同步。这只是意味着每次访问都将返回最新的值(而不是在线程中本地缓存的副本)。

    后增量不是原子操作,它是内存访问,然后是内存写入。交错两个可能意味着该值实际上只增加一次。

    【讨论】:

    • 不,两者之间的唯一区别是返回哪个值。预增量也是内存访问,然后是内存写入。
    • 在操作周围设置互斥锁/解锁并不是世界末日。人们担心线程可能会时不时地挂起。但在这种情况下,它是一个非常短的操作受到保护,并且两个线程同时到达那里的概率很小(但有限)。
    • Amardeep 是对的 - 内存屏障是昂贵的部分,无论您使用原子增量还是保护增量的锁都会发生这种情况。
    • @wowus:为什么不让你的唯一 ID 成为与线程本地计数器连接的线程 ID?然后每个线程可以生成自己的 ID 而无需锁定。
    • 我发现“与本地缓存在线程中的副本相反”的说法不清楚。可以拥有仍然需要 volatile 的单线程代码(即:用于信号处理程序更改的值)。所涉及的缓存更简单,并且 volatile 通常只需要指示编译器不要使用先前加载的寄存器内副本或堆栈溢出副本(如果方便)。
    【解决方案2】:

    不,您必须使用平台相关的原子访问。有几个库对这些进行了抽象——GLib 提供了可移植的原子操作,必要时可以回退到互斥锁,我相信 Boost 也提供了可移植的原子操作。

    正如我recently learned 一样,对于真正的原子访问,您需要一个完整的内存屏障,而volatile 不提供。所有 volatile 保证是在每次访问时都会重新读取内存,并且不会重新排序对 volatile 内存的访问。优化器可以在易失性读/写之前或之后重新排序一些非易失性访问 - 可能在您的增量中间! -- 所以你必须使用实际的原子操作。

    【讨论】:

    【解决方案3】:

    在现代快速多核处理器上,由于缓存和写入缓冲区,原子指令的开销很大。

    因此编译器不会仅仅因为您添加了volatile 关键字就发出原子指令。您需要使用内联汇编或特定于编译器的扩展(例如gcc atomic builtins)。

    我建议使用库。简单的方法是在要更新变量时锁定。如果信号量适合您正在做的事情,它们可能会更快。看来GLib 提供了一个相当有效的实现。

    【讨论】:

    • 有没有办法从 GLib 中只提取原子库?我宁愿不依赖于原子。
    【解决方案4】:

    Windows 提供InterlockedIncrement(和InterlockedDecrement)来执行您的要求。

    【讨论】:

    • 有点像我要找的东西,除了我需要与 linux 兼容。
    • 使用 TBB -- 跨平台(只要是 x86/x86_64)可靠的原子(以及许多其他东西)。
    【解决方案5】:

    Volatile 只是阻止优化,但原子性需要更多。在 x86 中,指令必须以 LOCK 前缀开头,在 MIPS 中,RMW 循环必须由 LL/SC 结构包围,...

    【讨论】:

      【解决方案6】:

      您的问题是 C 不保证增量运算符的原子性,实际上,它们通常不是原子的。为此,您必须使用像 Windows API 这样的库或编译器内置函数(GCCMSVC)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-27
        • 2015-08-06
        • 2011-03-03
        • 2018-05-31
        • 2016-11-05
        • 2011-06-25
        相关资源
        最近更新 更多