today I read AQS source code.I found some confuse place about AbstractQueuedSynchronizer#addWaiter
method:
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?