cha*_*eng 5 java java.util.concurrent
我在阅读JDK ConcurrentLinkedQueue时发现UNSAFE.compareAndSwapObject非常奇怪.(CLQ类是来自ConcurrentLinkedQueue的副本,以便于调试......)
当我向ConcurrentLinkedQueue提供第一项时.
在
p.casNext(null, newNode)
head == tail == p == t ref之前的同一个对象,就像这样.
之后进入casNext
UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
p.next按预期引用newNode,就像这样.
走出去提供
一切都变得奇怪......我可以理解为什么p.next ref伤口改为p,如何自动引导newNode ...
代码:ConcurrentLinkedQueue.class offer()
public boolean offer(E e) {
checkNotNull(e);
final Node<E> newNode = new Node<E>(e);
for (Node<E> t = tail, p = t;;) {
Node<E> q = p.next;
if (q == null) {
// p is last node
if (p.casNext(null, newNode)) {
// Successful CAS is the linearization point
// for e to become an element of this queue,
// and for newNode to become "live".
if (p != t) // hop two nodes at a time
casTail(t, newNode); // Failure is OK.
return true;
}
// Lost CAS race to another thread; re-read next
}
else if (p == q)
// We have fallen off list. If tail is unchanged, it
// will also be off-list, in which case we need to
// jump to head, from which all live nodes are always
// reachable. Else the new tail is a better bet.
p = (t != (t = tail)) ? t : head;
else
// Check for tail updates after two hops.
p = (p != t && t != (t = tail)) ? t : q;
}
}
Run Code Online (Sandbox Code Playgroud)
它的操作可能类似于下面的伪代码,但用所谓的本机代码 (C/C++) 编写,通常比 Java 快得多:
boolean compareAndSwapObject(Object obj, long fieldId, Object expectedValue, Object newValue) {
synchronized (globalExchangeLock) {
if (obj.fieldArray.get(fieldId) == expectedValue) {
obj.fieldArray.set(fieldId, newValue);
return true;
}
}
return false;
}
private static final Object globalExchangeLock = new Object();
Run Code Online (Sandbox Code Playgroud)
然而,传递fieldId并不复杂,也许应该被缓存,就像下面的 Java 代码(这次不是伪代码):
boolean compareAndSwapObject(Object obj, long fieldId, Object expectedValue, Object newValue) {
synchronized (globalExchangeLock) {
if (obj.fieldArray.get(fieldId) == expectedValue) {
obj.fieldArray.set(fieldId, newValue);
return true;
}
}
return false;
}
private static final Object globalExchangeLock = new Object();
Run Code Online (Sandbox Code Playgroud)
我的 Android 项目使用的是:
/*
* Written by Stefan Zobel and released to the
* public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package java8.util.concurrent;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
final class UnsafeAcc {
static final Unsafe unsafe;
static {
try {
Field field = null;
try {
field = Unsafe.class.getDeclaredField("theUnsafe");
} catch (NoSuchFieldException ignored) {
// For older Androids.
field = Unsafe.class.getDeclaredField("THE_ONE");
}
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
} catch (Exception e) {
throw new Error(e);
}
}
private UnsafeAcc() {
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2553 次 |
| 最近记录: |