Skip to main content

原子类 Atomic

huhxAbout 1 minjavaConcurrency-CollectionConcurrency

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

FAQ

总结

参考