【问题标题】:Java volatile array?Java易失性数组?
【发布时间】:2011-07-07 14:43:59
【问题描述】:

如何使数组易失?因为据我了解,使数组易失是不安全的?

【问题讨论】:

标签: java volatile


【解决方案1】:

编辑: 数组是java中的对象。如果您使对该对象的引用变为易失性,则如果您交换对数组的引用,则使其对其他线程可见。 但是,这不适用于数组值本身。

为了更好地理解 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?

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

旧: 编写自我参考 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)。

另一种可能是容器使用易失指针字段的指针结构。也没有那么高效...

【讨论】:

    【解决方案2】:

    将数组声明为 volatile 并授予对其字段的 volatile 访问权限。您是在声明引用本身是 volatile,而不是它的元素。
    换句话说,您声明的是易失性元素集,而不是易失性元素集

    这里的解决方案是使用AtomicIntegerArray,以防您想使用整数。另一种方法(但有点难看)是每次编辑字段时重写对数组的引用。

    你这样做:

    arr = arr; 
    

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

    【讨论】:

    • 我不认为可变的元素与原子的元素访问相同。
    • 你说得对,volatile 是关于保证发生前的关系。
    • 我真的不认为这是解决问题的方法。问题是(部分,据我了解)缓存一致性,以及在字节码系统和 JVM 本身的定义中几乎完全缺乏强大的内存排序语义。重写数组引用并不能保证您连贯地刷新您写入缓存或内存的任何数组元素,以便所有线程都具有相同的元素视图。
    【解决方案3】:

    这个怎么样:

    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 额外内存的权衡,但它是可管理的

    【讨论】:

    • 有趣的想法。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      • 2016-05-31
      • 2012-02-22
      • 1970-01-01
      相关资源
      最近更新 更多