AtomicReferenceFieldUpdater - 方法set,get,compareAndSet语义

时间:2011-11-24 22:17:14

标签: java concurrency volatile atomicreference jsr166

From the Java AtomicReferenceFieldUpdater docs

  

请注意,此类中compareAndSet方法的保证是   比其他原子类弱。因为这个班级无法保证   该领域的所有用途都适用于原子的目的   访问,它只能保证原子性和易失性语义   尊重compareAndSetset的其他调用。

这意味着我无法与compareAndSet一起执行常规易失性写入,但必须使用set。它没有提到有关get的任何内容。

这是否意味着我仍然可以读取具有相同原子性保证的易失性字段 - 所有写入setcompareAndSet之前的所有写入对于读取易失性字段的每个人都是可见的吗?

或者我必须在get上使用AtomicReferenceFieldUpdater而不是字段上的易失性读取吗?

如果您有参考,请发表参考文献。

谢谢。

编辑:

来自Java Concurrency in Practice,他们唯一说的是:

  

更新程序类的原子性保证弱于   普通的原子类因为你无法保证   底层字段不会直接修改 - compareAndSet   和算术方法只保证原子性相对于其他   线程使用原子字段更新器方法。

同样,没有提到其他线程应该如何读取这些易失性字段。

另外,我是否正确地假设“直接修改”是常规易失性写入?

2 个答案:

答案 0 :(得分:2)

这意味着对对象的引用将得到保证,但因为您可以使用任何对象,当另一个线程访问该对象时,该对象的字段可能无法正确写入。

可以保证的唯一方法是字段是最终的还是不稳定的。

答案 1 :(得分:2)

这不是问题的确切答案:

文档中既没有解释也没有意图。如果想要绕过全局排序,即在允许它的体系结构上进行易失性写入(如IBM Power或ARM),并且只是暴露CAS(LoadLinked / StoreCondition)行为而不用屏障,那将是一个非常惊人的努力和混乱的来源。

sun.misc.Unsafe的CAS没有规范或排序保证(以前称为),但是java.util.atomic ...没有。所以在较弱的模型java.util.atomic impl上。在这种情况下需要必要的围栏来遵循java规范。

假设Updater类实际上没有围栏。 如果它们这样做,则易变的字段读取(不使用get)将返回更新值,即明确get()是不需要的。由于没有订购保证,以前的商店可能不会传播(在弱模型上)。在x86 / Sparc TSO硬件上确保了java规范。

但是,这也意味着CAS可以使用以下非易失性读取进行重新排序。 java.util.concurrent.SynchronousQueue队列中有一个有趣的注释:

        // Note: item and mode fields don't need to be volatile
        // since they are always written before, and read after,
        // other volatile/atomic operations.

提到的所有原子操作都是AtomicReferenceFieldUpdater的CAS。这意味着正常的读写和AtomicReferenceFieldUpdater.CAS之间的缺乏或重写,即表现得像易失性写入。

        s.item = null;   // forget item
        s.waiter = null; // forget thread

        //....

        while ((p = head) != null && p != past && p.isCancelled())
            casHead(p, p.next);

只是CAS,没有易失性写入。

鉴于上述情况,我得出结论,AtomicXXXFieldUpdater暴露了与AtomicXXX对应物相同的语义。