点击上方“蓝字”关注我们,每天点亮一个新的技能点。
本文作者:无双老师云析学院VIP课程授课老师原子操作
原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换。 原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分,将整个操作视作一个整体是原子性的核心特征。原子类
在java中提供了很多原子类,主要把这些原子类分成 四大类 。原子更新基本类型或引用类型
- AtomicBoolean
- AtomicInteger
- AtomicLong
- AtomicReference
- AtomicMarkableReference
- AtomicStampedReference
原子更新数组中的元素
原子更新数组中的元素,可以更新数组中指定索引位置的元素,这些类主要有:- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray
原子更新对象中的字段
原子更新对象中的字段,可以更新对象中指定字段名称的字段,这些类主要有:- AtomicIntegerFieldUpdater
- AtomicLongFieldUpdater
- AtomicReferenceFieldUpdater
高性能原子类
高性能原子类,是java8中增加的原子类,它们使用分段的思想,把不同的线程hash到不同的段上去更新,最后再把这些段的值相加得到最终的值,这些类主要有:- Striped64
- LongAccumulator
- LongAdder
- DoubleAccumulator
- DoubleAdder
AtomicInteger使用
package com.example.atomic.atomicinteger.demo;import java.util.concurrent.atomic.AtomicInteger;/**
* @Author: 无双老师【云析学院:http://yunxiedu.net QQ:3190976240 email:zhouguanya20@163.com】
* @Date: 2020-03-21 16:20
* @Description: AtomicInteger使用方式
*/public class AtomicIntegerDemo {public static void main(String[] args) throws InterruptedException {
test1();
test2();
}private static void test1() throws InterruptedException {
Counter counter = new Counter();// 100个线程for (int i = 0; i < 10; i++) {// 每个线程对count累加10次new Thread(() -> {for (int j = 0; j < 1000; j++) {
counter.addCount();
}
}).start();
}
Thread.sleep(1000);
System.out.println("count = " + counter.getCount());
}private static void test2() throws InterruptedException {/**
* 原子性的int
*/
AtomicInteger count = new AtomicInteger();// 100个线程for (int i = 0; i < 10; i++) {// 每个线程对count累加10次new Thread(() -> {for (int j = 0; j < 1000; j++) {
count.incrementAndGet();
}
}).start();
}
Thread.sleep(1000);
System.out.println("count = " + count.get());
}
}/**
* volatile修饰的计数器
*/private volatile static int count = 0;public void addCount() {
count++;
}public int getCount() {return count;
}
AtomicInteger原理
AtomicInteger声明
public class AtomicInteger extends Number implements java.io.Serializable
Unsafe类的使用
// setup to use Unsafe.compareAndSwapInt for updatesprivate 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); }
}
AtomicInteger属性
private volatile int value;
AtomicInteger构造器
/**
* Creates a new AtomicInteger with the given initial value.
*
* @param initialValue the initial value
*/public AtomicInteger(int initialValue) {
value = initialValue;
}/**
* Creates a new AtomicInteger with initial value {@code 0}.
*/public AtomicInteger() {
}
AtomicInteger自增
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/public final int incrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
调用Unsafe类的方法如下。
public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;
}
注意观察
compareAndSwapInt即CAS方式修改int值。
AtomicInteger.incrementAndGet方法自增的原理:
- 调用unsafe.getAndAddInt方法
- unsafe.getAndAddInt方法通过自旋的方式,每次尝试通过CAS方法对原值进行累加。如果累加失败,将进入下一次循环。如果累加成功,则自旋结束。
免费技术直播
点击图片直达课堂
觉得不错,请点个在看吧~