代码之家  ›  专栏  ›  技术社区  ›  Alanpatchi

int基元类型的volatile声明

  •  13
  • Alanpatchi  · 技术社区  · 8 年前

    我引用了Oracle的Java文档 Atomic Access

    • 对于引用变量和大多数基本变量(除long和double之外的所有类型),读写都是原子的。
    • 对于所有声明的变量,读取和写入都是原子的 volatile (包括长变量和双变量)。

    我知道怎么做 不稳定的 作品但提到申报的要求 不稳定的 明确用于 long double 在第二条语句中,获取原子访问权的变量是 不稳定的 第一条语句中引用变量和大多数基元变量(除long和double之外的所有类型)的声明可选。

    但我看到的代码使用显式 不稳定的 在中声明 int 实现原子访问的原始类型;不这样做也不能保证原子访问。

    int variable1;          // no atomic access
    volatile int variable2; // atomic access
    

    我错过什么了吗?

    2 回复  |  直到 8 年前
        1
  •  11
  •   Thiyagu    8 年前

    第一条语句没有提到生成引用变量和基元变量(除了 long double ) volatile .

    上面写着 读取 长的 双重的 原子的 (默认情况下)。使 读取 属于 长的 双重的 原子的 他们需要 不稳定的 .

    原子性与 可见度 .

    同一文件的以下段落

    原子操作不能交错,因此它们可以在不担心线程干扰的情况下使用。然而,这并不能完全消除同步原子操作的需要,因为内存一致性错误仍然是可能的。使用易失性变量可以降低内存一致性错误的风险,因为对易失性变量的任何写入都会与该变量的后续读取建立“发生在之前”的关系。

    比如 a = 1 哪里 a 是一个 int (例如)是 原子的 但你仍然需要 不稳定的 如果您希望任务在任何时间都可见 后来的 正在读取线程。

    读/写长/双变量是一个复合动作,并使其 不稳定的 确保它是原子的。

        2
  •  6
  •   bowmore    8 年前

    这个 volatile 关键字不仅仅保证原子访问,它还提供 可见性保证 .

    double long 原语占用的空间是原语的两倍 int (64位)可以在两个32位块中更新其值。因此,如果没有volatile,您可以看到 长的 双重的 在这两个步骤之间。其他基本变量的情况并非如此。

    但原子访问与可见性不同。这个 不稳定的 关键字还保证在写入变量后,在其他线程上对该变量的所有读取都将看到新值。这就是为什么 不稳定的 在其他基本类型上仍然需要。

    当一个字段被声明为volatile时,编译器和运行时 请注意,此变量是共享的,对其进行的操作不应 使用其他内存操作重新排序。易失性变量不会缓存在 寄存器或在缓存中对其他处理器隐藏,因此 volatile变量始终返回任何线程最近的写操作。

    实践中的Java并发:3.1.4可变变量