Unsafe's method compareAndSwapObject mechanism

sonerila :

today I read AQS source code.I found some confuse place about AbstractQueuedSynchronizer#addWaitermethod:

    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;
    }

does pred value changed after compareAndSetTail in second if statement?

so I make a test for it. but it make me more and more confuse.

I found compareAndSetTail call compareAndSwapObject finally.

so I test compareAndSwapObject in Unsafe Package.

this is my test code

    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);
    }

and its output is:

preName:init-name
name:new-name

Why did name change, but preName keep the original value?

Pavel Smirnov :

compareAndSwapObject() does not work the way you (probably) expect. This could be so due to slightly confusing name.

It does not actually swaps the objects. It changes only name by checking if name == preName, and if so, it just updates its value. There's always one target field to be updated, not two.

BTW, here are good unofficial docs for Unsafe class. You can get some useful information from it.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=20391&siteId=1