目前JAVA除了使用synchronized关键字来控制进行共享数据的同步外,还引入了轻量级并发框架,以使得JAVA可以以优雅的面向对象的方式对共享数据进行同步,该并发框架在集合等框架中被广泛使用,而轻量级并发的实现原理就是CAS,所以深入理解CAS的实现,攻克轻量级并发这个山头堡垒,对于正确使用JAVA并发框架非常重要,所以本文蜻蜓点水大概了解下CAS的实现,不详细分析每一行代码,主要这种分析CAS实现的大概细节,有关指针,汇编等的细节,还请参考相关书籍,不正确地方指出,还望指出。
一 、 CAS的JNI JAVA入口类概述
在sun.misc包中,有这样一个类,Unsafe.java,这是java调用轻量级锁的入口,这里面大部分方法被声明为native方法,表明这里的功能大部分依赖底层的平台特性实现,该类位于
openjdk/jdk/src/share/classes/sun/misc/目录下,部分代码片段如下:
package sun.misc;
import java.security.*;
import java.lang.reflect.*;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
/**
* A collection of methods for performing low-level, unsafe operations.
* Although the class and all methods are public, use of this class is
* limited because only trusted code can obtain instances of it.
*
* @author John R. Rose
* @see #getUnsafe
*/
public final class Unsafe {
private static native void registerNatives();
static {
registerNatives();
sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
}
private Unsafe() {}
private static final Unsafe theUnsafe = new Unsafe();
@CallerSensitive
public static Unsafe getUnsafe() {
Class cc = Reflection.getCallerClass();
if (cc.getClassLoader() != null)
throw new SecurityException("Unsafe");
return theUnsafe;
}
/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
* @return <tt>true</tt> if successful
*/
public final native boolean compareAndSwapObject(Object o, long offset,
Object expected,
Object x);
// 其他代码忽略
}
从这个类的构造函数可看出,这个类不能被外部使用new 操作符创建对象,只能通过调用静态公有方法getUnsafe获取theUnsafe对象,而且普通的java类中调用Unsafe.getUnsafe()也不被允许,只能通过反射获取,如下:
public static Unsafe getUnsafeInstance() throws Exception {
Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
return (Unsafe) theUnsafeField.get(Unsafe.class);
}
这个类中的方法几乎都是native声明的,比如compareAndSwapObject
/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
* @return <tt>true</tt> if successful
*/
public final native boolean compareAndSwapObject(Object o, long offset,
Object expected,
Object x);
参数说明:
o:需要操作字段的对象
expected:期望的对象
x:需要交换的值
offset:需要操作的对象相对于o对象的地址偏移量,通过调用Unsafe.objectFieldOffset(Field field)获取,比如ConcurrentHashMap.HashEntry对next字段偏移量的获取
static final class HashEntry<K,V> {
// 其他代码忽略
volatile HashEntry<K,V> nex