Unsafe的方法compareAndSwapObject机制

Unsafe's method compareAndSwapObject mechanism

今天我阅读了 AQS 源代码 code.I 发现了一些关于 AbstractQueuedSynchronizer#addWaiter 方法的混淆之处:

    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

在第二个 if 语句中 compareAndSetTail 之后 pred 值是否发生变化?

所以我来测试一下。却让我越来越迷茫

我终于找到了 compareAndSetTail 调用 compareAndSwapObject

所以我在不安全包中测试compareAndSwapObject

这是我的测试代码

    private static final long nameOffset;
    private String name="init-name";
    static Unsafe unsafe = reflectGetUnsafe();
    static {
        try {
            nameOffset = unsafe.objectFieldOffset
                    (AQSTest.class.getDeclaredField("name"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    private static Unsafe reflectGetUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch (Exception e) {
            return null;
        }
    }
    @Test
    public void testUnsafe() {
        String preName = name;
        unsafe.compareAndSwapObject(this, nameOffset, preName, "new-name");
        System.out.println("preName:" + preName);
        System.out.println("name:" + name);
    }

它的输出是:

preName:init-name
name:new-name

为什么 name 改变了,但 preName 保持原来的值?

compareAndSwapObject() 并不像您(可能)期望的那样工作。这可能是由于名称有点混乱。

它实际上并不交换对象。它仅通过检查是否 name == preName 来更改 name,如果是,则仅更新其值。总是有 一个 个目标字段要更新,而不是两个。

顺便说一句,hereUnsafe class 的很好的非官方文档。你可以从中得到一些有用的信息。