Java volatile数组?

时间:2011-03-02 21:19:05

标签: java volatile

如何使数组易变?因为我已经明白,使数组变得不稳定是不安全的吗?

4 个答案:

答案 0 :(得分:17)

声明一个数组volatile 给它的字段提供volatile访问权限。你声明引用本身是易失性的,而不是它的元素。

换句话说,您宣布的是易变的元素,而不是一组易失性元素。 这里的解决方案是使用AtomicIntegerArray以防你想要使用整数。

另一种方式(但有点难看)是每次编辑字段时重写对数组的引用。

你这样做:

arr = arr; 

(正如我所说......丑陋)

答案 1 :(得分:7)

AtomicLongArray,AtomicIntegerArray,AtomicReferenceArray(java.util.concurrent.atomic)。

答案 2 :(得分:3)

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

更好地了解java内存模型,实际上有可能在没有Atomic * Array的情况下绕过它。使用发生在之前的关系进行易失性读取和正常写入使得它成为可能:

如果线程A在之后写入一些非易失性的东西和一个易失性变量,那么线程B也可以保证看到易失性内容的变化,但前提是线程B读取了volatile变量第一。 也可以看看: Happens-before relationships with volatile fields and synchronized blocks in Java - and their impact on non-volatile variables?

对于数组,这意味着: 写入数组后,写入一些易失性状态变量(确保写入实际更改易失性状态变量!) 从数组中读取时,首先读取易失性状态变量,然后访问该数组。 易失性读取也应该使所有其他写入也可见,只要它们发生在之前。

OLD: 写自我引用arr=arr实际上并没有帮助。

您编写数组arr的地址,而不是字段arr[i]的值。因此,您仍然不会获得arr[i](您想要的)的易失性属性,但仅限于存储地址arr

前面提到的Jeremy Manson的博文详细解释了它: http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html

他最好的解决方案是使用Atomic * Arrays,即AtomicReferenceArray用于泛型类型(基本类型也有特殊形式)。我无法想象这是特别有效的,特别是当它获得你需要的更多属性时(原子性>> volatile)。

替代方案可以是指针结构,其中容器使用易失性指针字段。也没那么有效......

答案 3 :(得分:1)

如何?

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;

细胞也使内容易挥发。也只有在预分配单元格之后,才将新数组分配给volatile数组...虽然可以牺牲Cell的额外内存,但是它是可管理的