高并发系列之——原子操作
jdk:1.8.0_65
1 前言
首先需要了解什么是原子性,可以理解为CPU层面不能分割的操作,原子性只有两种状态,要么改变,要么不改变。如果多线程同时更新同一个变量,非原子操作都会出现线程安全问题,导致多线程执行后获取到的变量值与期望值不一致。
那么如何解决线程安全问题呢,可以实现一个原子操作,有三种方式:
第一种:使用同步技术,sychronized代码块。
第二种:lock接口。
第三种:原子数据结构,如AtomicBoolean、AtomicInteger、AtomicLong等。
以下是针对原子数据结构进行解读。
2.原子数据结构
原子数据在jdk中包路径为java.util.concurrent.atomic,原子数据结构类都是使用Unsafe实现的包装类,有11个类,可以分为四种,以下为各个类型的讲解。
2.1 原子更新基本类型
AtomicBoolean:更新的 boolean 值。适用于多线程中状态控制,如销毁或是执行状态。
AtomicInteger:更新的 int 值。常用于资源数量的控制操作,如线程池中资源数量,以此来判断新的任务是否加入线程池中。
AtomicLong:更新的 long 值。
2.2 原子更新数组——更新数组中指定的值
AtomicIntegerArray:更新其元素的 int 数组。
AtomicLongArray:更新其元素的 long 数组。
2.3 原子更新引用类型——更新多个变量
AtomicReference:更新的对象引用。
AtomicMarkableReference:维护带有标记位的对象引用,可以原子方式对其进行更新。
AtomicReferenceArray:元素的对象引用数组。
AtomicStampedReference:维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。
2.4 基于反射的实用工具类——由于此类型都是抽象类,在使用前都需要调用newUpdater创建一个updater
AtomicIntegerFieldUpdater:可以对指定类的指定 public volatile int 字段进行原子更新。
AtomicLongFieldUpdater:可以对指定类的指定 public volatile long 字段进行原子更新。
AtomicReferenceFieldUpdater:可以对指定类的指定 public volatile 字段进行原子更新。
3.原子数据结构源码分析和示例
3.1 原子更新基本类型
1 package Atomic;
2
3 import java.util.concurrent.atomic.AtomicInteger;
4
5 public class AtomicMain {
6 //原子更新基本类型
7 private static void atomicBaseType() {
8 AtomicInteger atomicInteger = new AtomicInteger(10);
9 System.out.println("先返回当前值,然后递增1:" + atomicInteger.getAndIncrement());
10 System.out.println("更新后值:" + atomicInteger.get());
11 }
12
13 public static void main(String[] args) {
14 atomicBaseType();
15 }
16 }
运行结果:

3.2 原子更新数组
1 //原子更新数组
2 private static void atomicArray()
3 {
4 int[] atomicArray = new int[]{11,22,33};
5 AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(atomicArray);
6 for (int i = 0; i < atomicIntegerArray.length(); i++) {
7 System.out.println("原值:" + atomicIntegerArray.get(i));
8 atomicIntegerArray.incrementAndGet(i);
9 System.out.println("新值:" + atomicIntegerArray.get(i));
10 }
11 }
12 public static void main(String[] args) {
13 atomicArray();
14 }
运行结果:

3.3 原子更新引用类型
1 private static void atomicRefrence()
2 {
3 AtomicReference atomicReference = new AtomicReference();
4 Person person = new Person("张三", "男", 18);
5 atomicReference.set(person);
6 Person person1 = new Person("张三", "女", 20);
7
8 Person outPerson = (Person) atomicReference.getAndSet(person1);
9 System.out.println("本来身份:" + outPerson.getName() + " " + outPerson.getSex() + " " + outPerson.getAge());
10 Person outPerson1 = (Person) atomicReference.get();
11 System.out.println("两年后变性身份:" + outPerson1.getName() + " " + outPerson1.getSex() + " " + outPerson1.getAge());
12 }
13 public static void main(String[] args) {
14 atomicRefrence();
15 }
运行结果:

3.4 基于反射的实用工具类
1 //基于反射的实用工具类
2 private static void atomicRefect()
3 {
4 AtomicIntegerFieldUpdater atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(PersonUpdate.class, "age");
5 PersonUpdate person = new PersonUpdate("张三", "男", 20);
6 int outAge = atomicIntegerFieldUpdater.getAndAdd(person, 5);
7 System.out.println("当前信息:" + person.getName() + " " + person.getSex() + " " + outAge);
8 int outAge1 = atomicIntegerFieldUpdater.get(person);
9 System.out.println("五年后信息:" + person.getName() + " " + person.getSex() + " " + outAge1);
10
11
12 }
13 public static void main(String[] args) {
14 atomicRefect();
15 }
运行结果:

如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!

浙公网安备 33010602011771号