gpt4 book ai didi

Java 内存模型保证 volatile

转载 作者:行者123 更新时间:2023-12-01 13:37:28 24 4
gpt4 key购买 nike

我对 volatile 语义几乎没有怀疑。
假设有三个线程 T1、T2 和 T3 以及给定类的单个实例。

class Foo {
private int x = 1;
private int y = 2;
private int z = 3;
private volatile int w = 4;
private volatile int v = 5;

public void setX(int x) {
this.x = x;
}

public int getX() {
return this.x;
}

(...)
}

假设发生以下读/写操作序列:
1. (T1) foo.getX(); // stored in a local memory of T1
2. (T1) foo.getY(); // stored in a local memory of T1

3. (T2) foo.setX(10);
4. (T2) foo.setY(20);

5. (T3) foo.getY(); // T3 may see 2 or 20, no guarantees if a write action from point 4 is visible to T3
6. (T3) foo.setZ(30);
7. (T3) foo.setW(40);
8. (T3) foo.setV(50);

9. (T1) foo.getW()
10. (T1) foo.getZ()
11. (T1) foo.getY()
12. (T1) foo.getX()

我知道可以保证点 9 处的 T1 将看到在点 7 处设置的值,而在点 10 处的 T1 将看到在点 6 处设置的值(准确地说,至少与该值一样最新)。

但是,这些说法是真的吗?
  • Java 内存模型保证 T1 在第 11 点看到的值至少与 T3 在第 5 点看到的值一样(来自 T3 或更实际的本地内存,但即使它有更实际的值在共享内存中,它可能对 T1 不可见)。
  • 根本无法保证 T1 在第 12 点看到什么,特别是不能保证它看到在第 3 点设置的值。此外,如果在任何线程中对点 1 之前的 x 有任何写操作,T1 在点 12 可以看到一些陈旧的值(value)。
    如果在第 7 点 T3 的本地内存中有 x 的任何值,JMM 保证它会在第 12 点被 T1 看到,但假设在第 7 点之前没有对 T3 中的 x 进行写/读操作,则有没有这样的保证。
  • 第 8 点和第 9 点之间没有发生之前的关系,因为它们是不同的 volatile 变量。如果 JVM 以某种方式实现 Java 内存模型,它会在读取 volatile 变量时将本地内存刷新到共享内存,并在对 volatile 变量进行写操作时使本地内存无效,如 article 中的状态。对于同步语义,作为副作用,第 8 点和第 9 点之间会有一个发生在之前的关系,但它在 Java 语言规范中没有严格定义。
  • 如果在第 7 点和第 8 点会有读操作而不是写操作,则第 10 点的 T1 仍会看到值 30,因为发生之前的关系不仅适用于写-读 volatile 序列,而且适用于读-读、写-写以及读写 volatile 序列。

  • 请确认我的理解是正确的。

    最佳答案

    只要您的 get/set 操作只获取和设置变量,那么您的所有假设都是正确的。

    在 Java 中,变量存储在内存中。但是编译器(和运行时)将允许将变量临时存储在 CPU 缓存中,以便在算法或代码段期间进行更快的读写。

    这种缓存的缺点是,当 Core 处理完变量后,它将把它写回内存,就好像它只更新了一次一样。其他内核在使用变量时无法看到变量的状态。更糟糕的是,没有关于何时将它写回内存的顺序保证。

    通过将变量设置为 Volatile,您告诉 java 该变量不允许放入任何缓存中。对变量的读取或写入必须发生在内存中。

    这意味着 Volatile 将对变量 atomic 进行单次操作。但它也会使对变量的长时间操作变得更慢。因此 volatile 不是从多线程代码中获得性能提升的解决方案。

    值得注意的是,需要多次读取或写入的操作不是原子操作。例如,实际上是 i = i + 1 的 i++ 可以在写入完成之前更改 i 的值。

    如果您需要保证操作以原子方式发生,您可以使用锁或 semtex(慢),或者您可以使用像 Copy-On-Write (COW) 这样的聪明范式来允许原子读取和原子写入。

    关于Java 内存模型保证 volatile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60801410/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com