Java volatile array?

kpbwa7wx  于 12个月前  发布在  Java
关注(0)|答案(5)|浏览(75)

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

efzxgjgh

efzxgjgh1#

Java9引入了一种处理volatile数组的通用方法:VarHandle,允许对任何类型的数组进行原子操作。
下面是来自文档的自我描述示例:

String[] sa = ...
VarHandle avh = MethodHandles.arrayElementVarHandle(String[].class);
boolean r = avh.compareAndSet(sa, 10, "expected", "new");

可能值得注意的是,自Java9以来,来自“并发”包的原子类型(如AtomicInteger,AtomicIntegerArray,AtomicReference等)正在使用VarHandle而不是Unsafe来实现平台相关的操作,如“CompareAndSet”。

7kjnsjlb

7kjnsjlb2#

声明一个数组volatile并不给予volatile对其字段的访问。您声明的是引用本身的volatile,而不是它的元素。
换句话说,你声明的是一个
volatile元素集**,而不是一个volatile元素集
这里的解决方案是使用AtomicIntegerArray,以防你想使用整数。另一种方法(但有点丑陋)是在每次编辑字段时重写对数组的引用。
您可以通过以下方式实现:

arr = arr;

(as我说……丑)

vqlkdk9b

vqlkdk9b3#

编辑:数组是Java中的对象。如果使对该对象的引用为volatile,则在交换对数组的引用时使其对其他线程可见。然而,这并不适用于数组值本身。
为了更好地理解Java内存模型,实际上有可能在没有Atomic*Array的情况下绕过它。使用happened-before关系进行volatile读取和正常写入可以:
如果线程A写了一些非易失性的东西,然后写了一个易失性的变量 ,那么线程B也可以保证看到非易失性的东西的变化,但前提是线程B首先读取易失性变量。标签:Happens-before relationships with volatile fields and synchronized blocks in Java - and their impact on non-volatile variables?
对于数组,这意味着:在写入数组之后,写入一些volatile状态变量(确保写入实际上更改了volatile状态变量!)从数组中读取时,首先读取volatile状态变量,然后访问数组。volatile read应该使所有其他写入也可见,只要它们之前发生过。
老:编写自引用arr=arr实际上没有帮助。
您写入数组arr的地址,而不是字段arr[i]的值。因此,您仍然没有获得arr[i]的volatile属性(您想要的),而只是存储地址arr
前面提到的Jeremy曼森的博客文章详细解释了这一点:http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html
他的最佳解决方案是使用Atomic
Arrays,即用于泛型类型的AtomicReferenceArray(也存在用于基本类型的特殊形式)。我无法想象这是特别有效的,特别是当它为您获得更多您需要的属性(原子性>> volatile)时。
替代方案可以是指针结构,其中容器使用易失性指针字段。也没那么有效率。。

8yoxcaq7

8yoxcaq74#

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

c2e8gylq

c2e8gylq5#

不如这样吧:

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;

所述单元也使所述内容物挥发。我也分配新的数组到易失性的一个只有在预先分配的细胞.这是Cell额外内存的代价,但它是可管理的

相关问题