数组值的线程可见性更改



假设我有以下类:

private final int[] ints = new int[5];
public void set(int index, int value) {
    ints[index] = value;
}
public int get(int index) {
    return ints[index]
}

线程A运行以下内容:

set(1, 100);

(非常)在线程B运行以下内容后不久:

get(1)

我的理解是,不能保证线程B会看到线程A所做的更改,因为更改可能仍在CPU缓存/寄存器中。。。或者可能存在指令重新排序这是正确的吗

接下来,如果我有以下类,会发生什么:

public class ImmutableArray {
    public final int[] ints
    public ImmutableArray(int[] ints) {
        this.ints = ints
    }
}

具有以下局部变量:

volatile ImmutableArray arr;

线程A运行以下操作:

int[] ints = new int[5];
int[0] = 1;
arr = new ImmutableArray(ints);

(非常)在线程B运行以下内容后不久:

int i = arr.ints[0];

线程B是否因为final和发生在关系之前而保证获得值1,即使数组中的值设置在该值之外?

EDIT:在第二个例子中,数组从未更改,因此名称为"ImmutableArray"

第二版:

因此,我所理解的答案是,给定这个:

int a = 0
volatile int b = 0;

如果线程A执行以下操作:

a = 1;
b = 1;

然后线程B执行以下操作:

a == 1; // true
b == 1; // true

所以volatile起到了某种屏障的作用,但屏障在什么时候结束并允许重新排序指令?

你在这两方面都是正确的。事实上,即使你放松了你的问题陈述,你也是对的。

在第一个示例中,无论线程B稍后对get(1)求值多少,都不能保证它会观察到线程A对set(1, 100)的调用所写的值。

在第二个示例中,ints上的finalarr上的volatile就足以保证观察到ints[0] = 5。如果没有volatile,就不能保证观察到ImmutableArray实例本身,但只要观察到它,就可以保证在完全构建的状态下观察到它。更具体地说,保证涉及到构造函数返回时从对象的final字段可到达的完整状态。

最新更新