Java易失性数组?

Java易失性数组?,java,volatile,Java,Volatile,如何使数组不稳定?因为正如我所理解的,使数组易失性是不安全的?声明数组易失性不会给它的字段提供易失性访问。您正在声明引用本身是可变的,而不是其元素。 换句话说,您声明的是一组易失性元素,而不是一组易失性元素 这里的解决方案是在需要使用整数的情况下使用AtomicIntegerArray。另一种方法(但有点难看)是在每次编辑字段时重写对数组的引用 您可以通过以下方式实现: arr = arr; (正如我说的…丑陋)原子长数组、原子整数数组、原子引用数组(java.util.concurrent

如何使数组不稳定?因为正如我所理解的,使数组易失性是不安全的?

声明数组易失性不会给它的字段提供易失性访问。您正在声明引用本身是可变的,而不是其元素。
换句话说,您声明的是一组易失性元素,而不是一组易失性元素

这里的解决方案是在需要使用整数的情况下使用
AtomicIntegerArray
。另一种方法(但有点难看)是在每次编辑字段时重写对数组的引用

您可以通过以下方式实现:

arr = arr; 

(正如我说的…丑陋)

原子长数组、原子整数数组、原子引用数组(java.util.concurrent.atomic)。

编辑: 数组是java中的对象。如果将对该对象的引用设置为volatile,则在交换对该数组的引用时,将使该对象对其他线程可见。 但是,这对数组值本身并不适用

为了更好地理解java内存模型,实际上可以在没有原子*数组的情况下绕过它。使用易失性读取和正常写入的“发生在”关系可以:

如果线程A写了一些非易失性内容,然后又写了一个易失性变量,那么线程B也可以看到非易失性内容的变化,但前提是线程B首先读取易失性变量。 另见:

对于阵列,这意味着: 写入数组后,写入一些易失性状态变量(确保写入操作确实更改了易失性状态变量!) 从数组中读取时,首先读取volatile status变量,然后访问数组。 volatile read应该使所有其他写操作都可见,只要它们以前发生过

旧的: 编写自引用
arr=arr
实际上没有帮助

写入数组
arr
的地址,而不是字段
arr[i]
的值。因此,您仍然无法获得
arr[i]
(您想要的)的易失性属性,而只能获得存储地址
arr

杰里米·曼森(Jeremy Manson)之前提到的博文对此进行了详细解释:

他的最佳解决方案是使用原子*数组,即泛型类型的原子引用数组(基本类型也有特殊形式)。我无法想象这是特别有效的,尤其是当它为您获得更多您需要的属性时(原子性>>volatile)

另一种方法是指针式结构,其中容器使用易失性指针字段。也没有那么高效…

这个怎么样:

static class Cell<T> {
        volatile T elem;
    }

private Cell<T>[] alloc(int size){
        Cell<T>[] cells = (Cell<T>[]) (new Cell[size]);
        return cells;
    }

 volatile Cell<T>[] arr;
 Cell<T>[] newarr = alloc(16);
 for (int i = 0; i < newarr.length; i++) {
      newarr[i] = new Cell<>();
 }
 arr = newarr;
静态类单元格{
挥发性T元素;
}
专用单元格[]alloc(整数大小){
单元格[]单元格=(单元格[])(新单元格[大小]);
返回单元;
}
挥发性细胞[]arr;
单元格[]newarr=alloc(16);
for(int i=0;i

这些细胞也会使内容不稳定。另外,我只在预先分配单元后才将新数组分配给易失性数组。。。在单元额外内存方面有一个折衷,但它是可管理的

我不认为元素的易失性与元素的原子访问是一样的。你是对的,
易失性
是关于保证发生之前的关系。我真的不认为这是问题的解决方案。问题是(在某种程度上,据我所知)缓存一致性,以及字节码系统和JVM本身的定义中几乎完全缺乏强内存排序语义。重写数组引用并不能保证一致地刷新写入缓存或内存的任何数组元素,从而使所有线程都具有相同的元素视图。这是一个有趣的想法。