原子类 Atomic
About 1 min
Atomic
翻译成中文是原子的意思,是指一个操作是不可中断的。在多个线程一起执行的时候,能够保证一个操作一旦开始,就不会被其他线程干扰。今天我们就来学习下java中自带的一些原子类。
使用
原子类都存放在java.util.concurrent.atomic
下,这里以 AtomicInteger 为例子来介绍
AtomicInteger 类常用方法
分析
AtomicInteger 类的部分源码:
private static final Unsafe U = Unsafe.getUnsafe();
private static final long VALUE = U.objectFieldOffset(AtomicInteger.class, "value");
private volatile int value;
AtomicInteger
类主要利用CAS (compare and swap) + volatile和native方法来保证原子操作,从而避免 synchronized 的高开销,执行效率大为提升
CAS 的原理是拿期望的值和原本的一个值作比较,如果相同则更新成新的值。UnSafe 类的objectFieldOffset
方法是一个本地方法,这个方法是用来拿到变量的内存地址。另外value
是一个volatile
变量,在内存中可见,因此 JVM 可以保证任何时刻任何线程总能拿到该变量的最新值。
Unsafe类
Unsafe类似于C中的指针,compareAndSetInt方法是一个native方法:
public class UnsafeMain {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// 通过反射的方式获取Unsafe
var unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
var unsafe = (Unsafe) unsafeField.get(null);
// 分配1024 bytes的直接内存,并把整数42写入此内存地址中
long memoryAddress = unsafe.allocateMemory(1024);
unsafe.putInt(memoryAddress, 42);
System.out.println("address = " + Long.toHexString(memoryAddress));
// 从内存地址中读取整数
int value = unsafe.getInt(memoryAddress);
System.out.println("value = " + value);
// 释放直接内存
unsafe.freeMemory(memoryAddress);
}
}
输出结果如下:
address = 7f7b4c844000
value = 42