代码之家  ›  专栏  ›  技术社区  ›  Clark Gaebel

使用挥发性的,只要是原子

  •  4
  • Clark Gaebel  · 技术社区  · 16 年前

    如果我有这样的东西…

    volatile long something_global = 0;
    
    long some_public_func()
    {
        return something_global++;
    }
    

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

    注:我所用的是原子的增量和减量-没有什么比这更有趣的了。

    6 回复  |  直到 16 年前
        1
  •  16
  •   danben    16 年前

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

    Post-increment is not an atomic operation, it is a memory access followed by a memory write. Interleaving two can mean that the value is actually incremented just once.

        2
  •  4
  •   Community Mohan Dere    9 年前

    不,您必须使用依赖于平台的原子访问。有几个图书馆对这些进行了抽象-- GLib 提供可移植的原子操作,如果需要,可以返回到互斥锁,我相信Boost还提供了可移植的原子。

    recently learned 对于真正的原子访问,您需要一个完整的内存屏障, volatile 不提供。所有易失性保证都是在每次访问时重新读取内存,并访问 不稳定的 memory will not be reordered. It is possible for the optimizer to re-order some non-volatile access before or after a volatile read/write -- possibly in the middle of your increment! -- so you must use actual atomic operations.

        3
  •  3
  •   Artelius    16 年前

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

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

    我建议使用图书馆。最简单的方法是在您想要更新变量时获取一个锁。如果信号量适合您所做的工作,那么它可能更快。似乎 GLib

        4
  •  3
  •   Mark Ransom    16 年前

    Windows provides InterlockedIncrement (和) InterlockedDecrement 做你想做的事。

        5
  •  1
  •   ninjalj    16 年前

    volatile只会阻止优化,但原子性需要更多。在x86中,指令必须以锁前缀为前缀,在MIPS中,RMW循环必须由ll/sc构造包围,…

        6
  •  0
  •   Christoph    16 年前

    您的问题是C不能保证增量操作符的原子性,实际上,它们通常不是原子性的。你必须使用像 Windows API 编译器编译函数 GCC , MSVC 为此。