编辑:数组是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 他的最佳解决方案是使用AtomicArrays,即用于泛型类型的AtomicReferenceArray(也存在用于基本类型的特殊形式)。我无法想象这是特别有效的,特别是当它为您获得更多您需要的属性(原子性>> volatile)时。 替代方案可以是指针结构,其中容器使用易失性指针字段。也没那么有效率。。
5条答案
按热度按时间efzxgjgh1#
Java9引入了一种处理volatile数组的通用方法:VarHandle,允许对任何类型的数组进行原子操作。
下面是来自文档的自我描述示例:
可能值得注意的是,自Java9以来,来自“并发”包的原子类型(如AtomicInteger,AtomicIntegerArray,AtomicReference等)正在使用VarHandle而不是Unsafe来实现平台相关的操作,如“CompareAndSet”。
7kjnsjlb2#
声明一个数组volatile并不给予volatile对其字段的访问。您声明的是引用本身的volatile,而不是它的元素。
换句话说,你声明的是一个volatile元素集**,而不是一个volatile元素集。
这里的解决方案是使用
AtomicIntegerArray
,以防你想使用整数。另一种方法(但有点丑陋)是在每次编辑字段时重写对数组的引用。您可以通过以下方式实现:
(as我说……丑)
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
他的最佳解决方案是使用AtomicArrays,即用于泛型类型的AtomicReferenceArray(也存在用于基本类型的特殊形式)。我无法想象这是特别有效的,特别是当它为您获得更多您需要的属性(原子性>> volatile)时。
替代方案可以是指针结构,其中容器使用易失性指针字段。也没那么有效率。。
8yoxcaq74#
AtomicLongArray、AtomicIntegerArray、AtomicReferenceArray(java.util.concurrent.atomic)。
c2e8gylq5#
不如这样吧:
所述单元也使所述内容物挥发。我也分配新的数组到易失性的一个只有在预先分配的细胞.这是Cell额外内存的代价,但它是可管理的