繁体   English   中英

Java阵列同步(可见性)

[英]Java Array Synchronization (Visibility)

我试图准确理解元素可见性如何在java中的数组上工作。

鉴于课程:

class IntList {

    private final int[] array;

    public IntList(int[] array) {
        this.array = array;
    }

    public int[] readElements() {
        return Arrays.copyof(this.array, this.array.length);
    }

}    

以及用于创建实例的以下方法体:

int[] array = new int[length];
fillArrayWithRandomData(array); // puts data into the array from arbitrary source
return new IntList(array);

我想知道IntList中的元素IntList可以保证其他获得对返回的IntList的引用的线程可见?

我确信数组的参考将是可见的,因为它是最终的,但我似乎无法保证数组中的元素也是可见的。

注意: IntList类没有允许修改数组的方法,并且数组引用没有发布到任何其他对象,我只是想知道构造后的可见性。

编辑:对不起,我的类在我的实际实现中没有被称为String 我将类名更改为IntList因为似乎有太多的混淆。

编辑:我将在这里放置的最终答案是肯定的,元素是可见的。
@MikeClark找到了JLS答案:JLS§17.5“最终字段的使用模型很简单:在该对象的构造函数中设置对象的最终字段;并且不要在另一个地方写入正在构造的对象的引用线程可以在对象的构造函数完成之前看到它。如果遵循这个,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本。它还将看到任何对象的版本或由最终字段引用的数组,这些字段至少与最终字段一样是最新的。“

再次感谢!

因为您在构造函数中填充数组然后是,所以对new String(int[] array)任何调用都会在返回时初始化数组。 final关键字还将保证在分配时对array参数的最新更改将是可见的。

我发现这非常有用http://jeremymanson.blogspot.ch/2009/06/volatile-arrays-in-java.html所以基本上一切都发生在易失性读取保证被其他线程看到之前。 所以有一些黑客可以实现它。 另外,jaa提供本机AtomicReference / Long / Integer / ...数组支持。 这将确保其他线程可以看到更新。

你的问题中似乎混淆了很多不同的概念。

  • 能见度和final与彼此无关
  • 可见性和线程彼此无关
  • 一个private变量在类之外对任何其他代码都不可见,无论它是否是最终的
  • final数组仍然可以更改其元素。 它只是对数组本身的引用才是final

当你构造你的IntList对象(顺便说一句,感谢你改变名称),像这样:

public IntList(int[] array) {
    this.array = array;
}

内部this.array字段引用传递给构造函数的相同数组对象。 仍然可以从String类外部修改数组:

int[] array = {1, 2, 3};
IntList list = new IntList(array);
System.out.println(Arrays.toString(list.readElements()); // prints [1, 2, 3]
array[1] = 0;
System.out.println(Arrays.toString(list.readElements()); // prints [1, 0, 3]

您可以通过在构造函数中创建数组的副本来使您的类与此绝缘:

public IntList(int[] array) {
    this.array = Arrays.copyOf(array, array.length);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM