【Java多线程】-原子类型-java.util.concurrent.atomic

前言

在JDK5新增的并发包中有这样一个包:java.util.concurrent.atomic,该包是对Java部分数据类型的原子封装,在原有数据类型的基础上,提供了原子性的操作方法,保证了线程安全,本文我们以AtomicInteger为例,来看看原子类型是如何通过CAS实现原子性操作的。


Compare And Swap

CAS 指的是现代 CPU 广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。这个指令会对内存中的共享数据做原子的读写操作。其操作过程如下:

  • CPU 会将内存中将要被更改的数据与期望的值做比较。当这两个值相等时,CPU 才会将内存中的数值替换为新的值。否则便不做操作。
  • CPU 会将旧的数值返回。

简单来说,CAS 的含义是“我认为原有的值应该是什么,如果是,则将原有的值更新为新值,否则不做修改,并告诉我原来的值是多少”。
这一系列的操作是原子的。它们虽然看似复杂,但却是 Java 5 并发机制优于原有锁机制的根本。这是一种乐观锁的思路,它相信在它修改之前,没有其它线程去修改它;而Synchronized是一种悲观锁,它认为在它修改之前,一定会有其它线程去修改它,悲观锁效率很低。


AtomicInteger

下面我们以AtomicInteger为例,来看看原子类型是如何通过CAS实现原子性操作的。
volatile变量

private volatile int value;
public final int get() {
    return value;
}

首先声明了一个volatile变量value,volatile关键字保证了变量的内存可见性,保证共享变量被线程加载到工作内存的值是最新的;
内存可见性:一个线程对共享变量的写操作对后续其他线程的读操作可见。


Compare And Set

// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;// 注意是静态的

static {
  try {
    valueOffset = unsafe.objectFieldOffset
        (AtomicInteger.class.getDeclaredField("value"));// 反射出value属性,获取其在内存中的位置
  } catch (Exception ex) { throw new Error(ex); }
}

public final boolean compareAndSet(int expect, int update) {
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

这里利用Unsafe类的JNI方法实现,使用CAS指令,可以保证读-改-写是一个原子操作。compareAndSwapInt有4个参数,this - 当前AtomicInteger对象,valueOffset- value属性在内存中的位置(需要强调的是不是value值在内存中的位置),expect - 预期值,update - 新值。根据上面介绍的CAS操作过程,当内存中的value值等于expect值时,则将内存中的value值更新为update值,并返回true,否则返回false。


原子性方法
AtomicInteger中提供了许多原子性方法,比如public final int getAndIncrement (),public final int getAndSet (int newValue),public final int incrementAndGet ()等,下面看看incrementAndGet的源码,该方法的作用是在原有值的基础上+1,返回+1后的值:

public final int incrementAndGet() {
    for (;;) {// 这样优于while(true)
        int current = get();// 获取当前值
        int next = current + 1;// 设置更新值
        if (compareAndSet(current, next))
            return next;
    }
}

从源码中可以看到使用了compareAndSet方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值