我发现UNSAFE.compareAndSwapObject在阅读JDK ConcurrentLinkedQueue时非常奇怪。( CLQ类是从ConcurrentLinkedQueue复制的,以便于调试.)
当我向ConcurrentLinkedQueue提供第一项时。
p.casNext(null, newNode) head==tail==p==t之前引用相同的对象,如下所示。
http://i.stack.imgur.com/8dCO0.pngUNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
按照预期,p.next将引用到newNode,如下所示。
http://i.stack.imgur.com/mNtUN.png代码: ConcurrentLinkedQueue.class ()
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;
}
}发布于 2022-11-12 08:19:31
它的操作可能类似于下面的伪代码,但是用所谓的本机代码(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();然而,传递fieldId并不复杂,可能应该缓存,就像下面的Java代码(这次不是伪代码):
public class MyClass {
int myField;
// ...
private static final sun.misc.Unsafe U = UnsafeAcc.unsafe;
private static final long MY_FIELD_ID;
static {
try {
MY_FIELD_ID = U.objectFieldOffset(
MyClass.class.getDeclaredField("myField")
);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
}在我的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() {
}
}https://stackoverflow.com/questions/22076083
复制相似问题