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 }
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/7bdde537857175ebd4b196725bba25bb.png)
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 }
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/d892f9b0f3e55e080ddfdfebf918ef98.png)
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 }
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/4c7c7cd6c674035634c4fce8dc0acca4.png)
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 }
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/4c9c2129c6d8f45b675c21ccd6c11150.png)
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!