在并发编程中,为了防止多线程访问造成的不安全性,我们可以用到synchronized锁(悲观锁),ReentrantLock(重入锁),和原子类(乐观锁)等技术来提高安全性。今天我们就来深入理解一下原子类的实现方式。
J.U.C下的Atomic*类
atomic:原子的。代指不可再分割的意思,映射到Java代码中的意思是,这段代码中所执行的操作,要么都执行,要么都不执行。不存在一部分执行,一部分未执行的情况。
Java中的原子类是靠sun公司基于CAS实现的,Atomic类利用的是Unsafe类,是在sun.misc包下,不属于Java标准。
在这里我们模拟一下AtomicInteger类的实现方式。
AtomicInteger类源码分析
AtomicInteger 是一个支持原子操作的 Integer 类,就是保证在增加或者减少这个共享数据的时候,这个数据不会被重复加减或者被重复覆盖加减操作。我们来看一下他的源码实现:1
2
3
4
5
6
7
8public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
这是AtomicInteger中自增的方法源码,步长为1。
current:是原来内存中值。
next:是新值。
compareAndSet(current, next)方法源码:1
2
3public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
compareAndSwapInt()是一个本地方法(非Java语言实现),里边执行的是CAS操作。整个过程就是先获取value的值,再加1,然后进行CAS操作,如果在读取value值和加1的过程中value的值被其他线程改变了,那么CAS失败,一直循环到成功为止。至于其他getAndAdd之类的方法也都差不多,读者可以自行分析。在这里其实我们已经可以想到compareAndSwapInt()方法应该是同步的,或者里边实现的代码有部分是同步,要不然多线程下依旧是不安全的。至于具体是如何实现的,笔者能力有限读者可以参考https://blog.csdn.net/ls5718/article/details/52563959。
CAS算法
CAS(Compare-And-Swap)比较和交互,该方法保证了数据操作的原子性。CAS算法的实现,并不是在软件层面上的,该算法是硬件对并发操作共享数据的支持。
CAS中包含三个操作数:
- 内存实际值V。
- 预估值A(就是你更改之前,需要改变的量的估计值)。
- 更新值B。
在一个原子操作里面:比较V和A的值,如果V=A则将B值赋给V。
参考:
https://www.cnblogs.com/zhengbin/p/5657707.html
https://blog.csdn.net/ls5718/article/details/52563959