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
,如果是,则仅更新其值。总是有 一个 个目标字段要更新,而不是两个。
顺便说一句,here 是 Unsafe
class 的很好的非官方文档。你可以从中得到一些有用的信息。
今天我阅读了 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
,如果是,则仅更新其值。总是有 一个 个目标字段要更新,而不是两个。
顺便说一句,here 是 Unsafe
class 的很好的非官方文档。你可以从中得到一些有用的信息。