千家信息网

高级并发编程系列之什么是原子类

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容介绍了"高级并发编程系列之什么是原子类"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.考考
千家信息网最后更新 2026年11月03日高级并发编程系列之什么是原子类

本篇内容介绍了"高级并发编程系列之什么是原子类"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1.考考你

相信作为资深程序员的你,对于AtomicInteger这样的类,即以Atomic开始的类一定不会感到陌生。我们在翻看很多框架源码、或者第三方组件都会经常看到它们,如影随形。

那么问题来了,像Atomicxxx这样的类,到底是什么意思呢?从字面意思比较好理解,Atomic即原子性,那么Atomicxxx即原子类。讲到这里,你一定还记得我们说过线程安全的三个基本要素,我们一起来回顾一下:可见性、原子性、有序性。原子类的原子性,讲的就是这个原子性,于是你可以先记住一个结论:原子类,它是线程安全的类。

到这里有朋友可能会提出质疑:你说线程安全,就线程安全吗?我不服,你没有讲清楚。我不听,我不听......好吧,看官们莫急,且听我一步一步分析,娓娓道来,话说......

#考考你:1.你真的理解原子类的核心思想吗2.你在你的项目中,有直接用到过原子类吗

2.案例

2.1.自增操作案例

2.1.1.普通变量版本

案例描述:

  • 定义一个普通的int型变量value,初始值为:0

  • 开启两个线程thread_1,thread_2并行执行value++操作

  • 每个线程执行 5000次,预期执行结果: 2 * 5000 = 10000次

  • 通过观察最终执行结果,是否等于预期10000次

  • 结果不相等,说明线程不安全,原因是:value++操作不是一个原子性操作

package com.anan.edu.common.newthread.atomic;/** * 普通 int变量 ++ 操作,非原子性,线程不安全 * * @author ThinkPad * @version 1.0 * @date 2020/11/29 8:27 */public class CommonIntDemo {    /**     * 普通成员变量     */    private int value = 0;    public  void addValue(){        value++;    }    public static void main(String[] args) throws InterruptedException {        // 1.创建CommonIntDemo对象        CommonIntDemo demo = new CommonIntDemo();        // 2.创建2两个线程,每个线程调用方法addValue 5000次        // 预期value值结果等于:2 * 5000 = 10000        int loopEnd = 5000;        Thread thread_1 = new Thread(() -> {            for(int i = 0; i < loopEnd; i++){                demo.addValue();            }        }, "thread_1");        Thread thread_2 = new Thread(() -> {            for(int i = 0; i < loopEnd; i++){                demo.addValue();            }        }, "thread_2");        // 3.启动执行线程        thread_1.start();        thread_2.start();        // 4.主线程等待子线程执行完成,打印value值        thread_1.join();        thread_2.join();        System.out.println("int型成员变量value最终结果:" + demo.value);    }}

执行结果分析:

2.1.2.AtomicInteger版本

案例描述:

  • 定义一个AtomicInteger变量value,初始值为:0

  • 开启两个线程thread_1,thread_2并行执行value.incrementAndGet()操作

  • 每个线程执行 5000次,预期执行结果: 2 * 5000 = 10000次

  • 通过观察最终执行结果,是否等于预期10000次

  • 结果相等,说明线程安全,原因是:原子类同时满足了可见性、与原子性

package com.anan.edu.common.newthread.atomic;import java.util.concurrent.atomic.AtomicInteger;/** * 原子类AtomicInteger,实现自增操作,线程安全 * * @author ThinkPad * @version 1.0 * @date 2020/11/29 8:27 */public class AtomicIntegerDemo {    /**     * AtomicInteger成员变量     */    private AtomicInteger value = new AtomicInteger(0);    public  void addValue(){        value.incrementAndGet();    }    public static void main(String[] args) throws InterruptedException {        // 1.创建AtomicIntegerDemo对象        AtomicIntegerDemo demo = new AtomicIntegerDemo();        // 2.创建2两个线程,每个线程调用方法addValue 5000次        // 预期value值结果等于:2 * 5000 = 10000        int loopEnd = 5000;        Thread thread_1 = new Thread(() -> {            for(int i = 0; i < loopEnd; i++){                demo.addValue();            }        }, "thread_1");        Thread thread_2 = new Thread(() -> {            for(int i = 0; i < loopEnd; i++){                demo.addValue();            }        }, "thread_2");        // 3.启动执行线程        thread_1.start();        thread_2.start();        // 4.主线程等待子线程执行完成,打印value值        thread_1.join();        thread_2.join();        System.out.println("AtomicInteger型成员变量value最终结果:" + demo.value);    }}

执行结果分析:

2.2.原子类底层原理分析

2.2.1.再次分析线程安全核心思想

通过比较普通类型int型变量自增操作,与原子型AtomicInteger型变量自增操作。我们看到应用层代码几乎没有差异,仅仅是通过AtomicInteger替换int实现自增操作,即保证了线程安全。那么AtomicInteger它是如何做到的呢?

要分析清楚AtomicInteger底层原理,还需要回到我们说过的线程安全基本要素:可见性、原子性、有序性。就是说不管通过什么手段,要实现线程安全,一定要满足这三个基本要素,换句话说,满足了三个基本要素,也即实现了线程安全。

那么我们就从这三个要素开始分析。首先看最容易理解的有序性,你还记得什么是有序性吗?它是说线程内有序,线程之间无序。有序性比较好理解,我们就不过多解释了。

再来看可见性,同样你还记得什么是可见性吗?我们知道jmm内存模型,每个线程都有自己的私人空间(工作内存),所有线程共享公共空间(主内存)。那么如果要保证某个变量在线程间的可见性,即当线程A操作该变量后,需要同步将变量值从私人空间同步到公共空间:工作内存--->主内存;同理其它线程在操作变量前,需要从公共空间将变量值同步到私人空间:主内存--->工作内存。java编程语法上给我们提供了一个关键字:volatile。用于实现可见性。你可能还需要下面这个图:

最后再来看原子性,原子性你应该还记得,我们上一篇:高级并发编程系列十二(一文搞懂cas)刚刚分享过。cas本质上是不到黄河心不死,什么意思呢?即是不释放cpu,循环操作,直到操作成功为止。我们是这么解释的,你也应该还记得对吧。而且我们还说过对于cas,它的操作原理是三个值:内存值A、期望值B、更新值C。每次操作都会比较内存值A,是否等于期望值B、如果等于则将内存值更新成值C,操作成功;如果内存值A,不等于期望值B,则操作失败,进行下一次循环操作。你可能还需要下面这个图:

好了到这里,我们可以一起来看AtomicInteger的源码了。看看是否满足我们说的可见性、原子性。进一步分析清楚AtomicInteger类线程安全的实现原理。下面我们通过截图+文字描述的方式,方便你理解。

2.2.2.AtomicInteger类声明

先来看AtomicInteger类的声明,这一块对于不熟悉的朋友可能比较难看懂,我们先截图看一下。

2.2.3.方法incrementAndGet分析

通过类声明部分源码,我们看到线程安全的可见性,通过volatile关键字修饰value成员变量,已经有了保障。那么原子性,又是如何保障的呢?答案是通过Unsafe工具类,进行cas操作来保障的。看图:

2.3.juc原子类分类

相信通过上面的分析,你已经理解了原子类线程安全的底层实现原理,如果你理解起来稍微还有点难度,我建议你多看两遍。对于一个程序员来说,我们不应该只会用用框架,底层思想和原理才是内功。

那么关于原子类的底层分析,我们暂时放一放,下面我们一起来看一下juc包中提供的常见原子能力工具类。它们每一个的底层原理,都在上面分析过了,我就不再逐一分析了,只是简单的列举出来,如果你感兴趣的话,可以找一两个按照我上面的分析思路,自己分析一下,应该会有意想不到的惊喜!

  • 基本原子类,代表:AtomicInteger、AtomicLong

  • 数组原子类,代表:AtomicIntegerArray、AtomicLongArray

  • 引用原子类,代表:AtomicReference。关于引用原子类,稍微加一句:它可以把一个普通对象,包装成具有原子能力的对象

  • 提供升级能力原子类,代表:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater

  • 累加器原子类,代表:LongAdder。关于累加器,稍微多加一句:它是jdk1.8开始后新加入的小伙伴,性能比起AtomicLong来说杠杠的。

"高级并发编程系列之什么是原子类"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

线程 原子 安全 分析 变量 结果 内存 原理 普通 有序 底层 空间 三个 两个 代表 成员 有序性 案例 要素 编程 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广州大一互联网络科技有限公司 科技互联网产品 互联网科技社 期待互联网科技 成都狮子座互联网科技 国外互联网科技网站 海南购全球互联网科技 卫星互联网科技股票 成都玖崟互联网科技有限公司乐商圈怎么样 现代科技和互联网有关系吗 宁波青枫互联网科技有限公司 温州喔噻互联网科技有限公司 互联网科技大奖都有哪些公司 晋城互联网科技 互联网科技大赛获奖感言 互联网数据科技专业 广州千川互联网科技有限公司 互联网科技包装股份有限公司上市 华人运通互联网科技公司 互联网科技创业计划的风险分析 互联网科技工作委员会 极限挑战互联网科技 上海喔噻互联网科技 无锡溥仪互联网科技有限公司 青海省互联网新科技 重庆威客帮互联网科技 下一代互联网重大应用科技园 福仕德教育科技互联网 北京军民互联网科技公司 利用互联网等科技手段
0