首页 > 其他分享 >AtomicInteger详解

AtomicInteger详解

时间:2023-08-27 23:32:30浏览次数:51  
标签:int AtomicInteger 原子 ++ 详解 线程 操作

AtomicInteger定义

  1. AtomicInteger类是系统底层保护的int类型,通过对int类型的数据进行封装,提供执行方法的控制进行值的原子操作,但AtomicInteger ≠ Integer。
  2. AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。


AtomicInteger使用场景

  1. AtomicInteger提供原子操作来进行Integer的使用,适合高并发情况下的使用。
  2. foreach作循环的时候需要对应参数进行自增或者自减操作。


AtomicInteger作用

分析普通Java的运算操作:

Java 中的运算操作在多线程是线程不安全的。比如 i++ 会解析为 i=i+1,Java 程序会把算式分为 3 个操作,获取值,计算值,赋予值,i++这个操作不具备原子性,多线程并发共享变量时必然会出现问题。

原子性:指的就是一个操作是不可中断,即使有多个线程执行,一个操作开始也不会受其他线程影响,即可以理解为线程的最小执行单元,不可被分割


线程不安全:一个线程计算出值后,还未重新给变量赋值,另一个线程来读取到这个值,就会造成线程不安全的问题


加锁:有时候需要通过加锁的方式去保证线程安全,但是加锁对性能会有很大的影响。

AtomicInteger的作用:就是让程序在不加锁的时候也能保障线程安全

public class TestAtomicInteger {
    static int b = 0;

    public static void main(String[] args) throws InterruptedException {
        AtomicInteger a = new AtomicInteger(0);
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                a.incrementAndGet();
                b++;
            }

        });
        t1.start();
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                a.incrementAndGet();
                b++;
            }
        });
        t2.start();
        Thread.sleep(1000);

        System.out.println("a=" + a);
        System.out.println("b=" + b);
    }
}

运行结果:

a=20000
b=16306

AtomicInteger对原子操作的常用方法

  • addAndGet()- 以原子方式将给定值添加到当前值,并在添加后返回新值
  • getAndAdd() - 以原子方式将给定值添加到当前值并返回旧值。
  • incrementAndGet()- 以原子方式将当前值递增1并在递增后返回新值。它相当于i ++操作。
  • getAndIncrement() - 以原子方式递增当前值并返回旧值。它相当于++ i 操作。
  • decrementAndGet()- 原子地将当前值减1并在减量后返回新值。它等同于i-- 操作。
  • getAndDecrement() - 以原子方式递减当前值并返回旧值。它相当于-- i 操作。

AtomicInteger底层原理(源码解析)

基于CAS的乐观锁实现

乐观锁是一种乐观思想,即认为每次取数据得时候都认为别的线程不会正在修改,所以不加锁,写数据的时候判断当前值与期望值是否相等,一样则更新,否则继续进行CAS操作。

unsafe是java提供的获得对对象内存地址访问的类,作用是在更新操作时提供“比较并替换”的作用,实际上就是AtomicInteger中的一个工具。

valueOffset是用来记录value本身在内存的编译地址的,也是为了更新操作在内存中找到value的位置。

unsafe提供了objectFieldOffset()方法用于获取某个字段相对Java对象的“起始地址”的偏移量,也提供了getInt、getLong、getObject之类的方法可以使用前面获取的偏移量来访问某个Java对象的某个字段。

注意:value是用来存储整数的时间变量,这里被声明为volatile,就是为了保证在更新操作时,当前线程可以拿到value最新的值(并发环境下,value可能已经被其他线程更新了)。


jdk1.8版本之前,AtomicIntege实现原子操作如下:

incrementAndGet代码,先获取到当前的 value 属性值,然后将 value 加 1,赋值给一个局部的 next 变量,然而,这两步都是非线程安全的,但是内部有一个死循环,不断去做compareAndSet操作,直到成功为止,也就是修改的根本compareAndSet方法里面。


public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

compareAndSet代码:


public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

compareAndSwapInt代码,此方法为 native 方法,compareAndSwapInt 基于的是CPU 的 CAS指令来实现的。通过compareAndSwapInt方法,循环操作对传进来的旧值和新值进行对比和更新,两值不一致就进行更新操作,从而达到自增的结果。


publicfinal native boolean compareAndSwapInt(Object var1, long var2, int var4, intvar5);

在jdk1.8版本之后,AtomicInteger具体是如何实现的原子操作

jdk1.8封装了U.getAndAddInt()

标签:int,AtomicInteger,原子,++,详解,线程,操作
From: https://blog.51cto.com/u_11354383/7255182

相关文章

  • G5、Pix2Pix详解
    ......
  • 依赖倒转原则详解
    依赖倒转原则基本介绍依赖倒转原则(DependenceInversionPrinciple):1.高层模块,不要依赖底层模块,二者都应该依赖其抽象。2.抽象不应该依赖细节,细节应该依赖抽象。3.依赖倒转的核心思想是面向接口编程。4.依赖倒转原则基于这样的设计理念:相对于细节的多变,抽象的东西就稳定......
  • 最完整的 generatorConfig.xml 配置详解
    <?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEgeneratorConfigurationPUBLIC"-//mybatis.org//DTDMyBatisGeneratorConfiguration1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">&......
  • JVM调优工具详解及调优实战
    前置启动程序事先启动一个web应用程序,用jps查看其进程id,接着用各种jdk自带命令优化应用 Jmap此命令可以用来查看内存信息,实例个数以及占用内存大小 jmap-histo14660#查看历史生成的实例jmap-histo:live14660#查看当前存活的实例,执行过程中可能会触发一次full......
  • Modbus协议详解1:Modbus的简介
    Modbus协议是应用非常广泛的一种通信协议规约,也是最早应用在工业现场的协议。早在1979年出现工业串行链路以来,Modbus的应用就开始普遍起来,它使得各种自动化设备之间的互相通信得到实现,做嵌入式产品开发的朋友应该不会陌生,Modbus的身影是随处可见的。并且在中国Modbus都已经形成了规......
  • linux下vim命令详解
    高级一些的编辑器,都会包含宏功能,vim当然不能缺少了,在vim中使用宏是非常方便的::qx    开始记录宏,并将结果存入寄存器xq    退出记录模式@x    播放记录在x寄存器中的宏命令稍微解释一下,当在normal模式下输入:qx后,你对文本的所有编辑动作将会被记录下来,再次输入q即退......
  • 最短路三种算法详解
    最短路最短路问题即,给你一张图,让你求出图中两点的最短距离。这篇文章会讲解\(Dijkstra\)、\(Spfa\)、\(Floyd\)三种算法,让您透彻理解最短路!Dijkstra朴素版题目:\(Dijkstra\)通常是用来解决图中一个定点到其余点的最短距离,基本思路是:从中心向外扩展,直到扩展到终点为止。......
  • ChatGPT全称是什么?一文详解chatGPT含义、特点及未来发展
    一、引言近年来,人工智能(AI)技术的迅猛发展为人类生活带来了诸多变革。其中,聊天机器人(Chatbot)作为AI领域的重要应用之一,逐渐融入了我们的日常生活。而在这个领域中,ChatGPT成为了备受瞩目的明星产品。那么,ChatGPT全称是什么?它的含义又是怎样的呢?本文将详细解析ChatGPT的含义、特点以......
  • 垃圾收集器ParNew&CMS与底层三色标记算法详解
    垃圾收集算法分代收集理论当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。比如在新生代中,每次收集都会有大量对象(近9......
  • 跨境电商需要用到的电商API详解(淘宝京东拼多多1688API)
    随着电子商务的快速发展,跨境电商已经成为越来越多企业的选择。在跨境电商的业务流程中,电商API发挥着至关重要的作用。本文将详细介绍跨境电商需要用到的电商API,包括商品信息、商品类目信息、店铺信息、交易明细信息、商品管理、评价信息、店铺用户信息等。一、商品信息API  获......