• 高并发系列之——原子操作


     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     }

    运行结果:

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

  • 相关阅读:
    KAL1 LINUX 官方文档之kali nethunter文档 ---MANA Evil Access Point
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter MAC改变器
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter Kali服务
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter HID键盘攻击
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter DuckHunter攻击
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter自定义命令
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter Application Terminal
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter BadUSB攻击
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter USB-Arsenal
    KAL1 LINUX 官方文档之kali nethunter文档 ---NetHunter KeX 管理器
  • 原文地址:https://www.cnblogs.com/guobm/p/9817979.html
Copyright © 2020-2023  润新知