在Java的多线程开发中需要做一些同步的操作。
在java concurrent库中提供了一系列支持原子操作的类,在atomic包下。
这里分析其中的AtomicInteger源码,来看看他是如何实现原子操作的。
AtomicInteger源码比较简单,主要的操作是对一个int值进行加减操作。
但是其中应用到了一个神奇的类Unsafe.java.
Unsafe.java提供了一些列的方法支持对JVM内存的操作(当然了他提供的功能远远不止操作内存)。
你看的没错是直接的操作内存,这个对于习惯了写Java程序时由GC直接管理内存的我这个小白来说,简直是三观尽毁。
Unsafe.java竟然是反Java常规的,那么想要使用它也不是那么随便的。默认Unsafe.java只信任JDK中的类,所以在自定义的类中不能直接实例化这个类,当然你还是可以通过反射来获取该对象。(额,扯远了)
通过观察代码发现AtomicInteger的原子性就是通过Unsafe.java来实现的。主要代码如下:
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private volatile int value; //注意value变量的volatile属性
功能:
- 获取Unsafe对象
- 通过反射获取AtomicInteger类中value在内存中的位置。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
功能:
通过CAS算法,设置value的值。CAS算法就是先比较value的值和expect的值是否相同,如果相同就设置update。如果不相同则设置失败。
这样就保证了,对value的原子操作。