老王:小陈啊,从今天开始我们就要进入Atomic原子类系列的学习 了,首先啊给你看一下JDK中提供给我们使用的原子类有哪些?
小陈:好啊,我记得JUC 下面提供的原子类还是挺多的,所有的原子类的使用和底层实现的原理都全部要掌握吗?
老王:其实啊,JUC 包下提供的原子类底层的实现原理基本都是差不多的 ,都是基于volatile和CAS操作来保证线程安全的,我们只需要掌握常用的一些原子类就可以了。
老王:至于这些原子类底层实现的原理,我们挑选几个比较有代表性 的来讲,深入到源码级别,以及底层实现的细节;理解了我们讨论的这几个,你再去看其它的几个实现,发现都是一样的套路。
老王:哎呀,废话多了,不多说了,直接给你看下JUC给我哪些原子类:
看上面的图形,我们使用红色圈中的那些,就是我们需要讨论的,一共分为一下几个类别:
(1)AtomicInteger、AtomicLong整型的原子类
如果我们在程序中使用了基本的Integer、Long 等类型,进行基本的数学加减运算、赋值操作等。但是如果是在多线程环境下多个线程同时操作同一个Integer、Long变量,可能导致线程安全的问题。
要规避线程安全 的问题,你可能需要用到锁 ,比如常用的synchronized、ReentrantLock锁 等,让同一时间只有一个线程操作变量;但是锁是一个比较重的操作 ,可能导致线程获取不到锁而陷入沉睡,这样就会导致并发的性能降低。
然而如果你需要很高的并发性能,不想用锁 ,但需要是线程安全的 ;在这种情况下JUC 就为我们提供了 线程安全的原子类AtomicInteger、AtomicLong等,在多线程环境下进行加减运算、赋值操作等都是线程安全的。
AtomicInteger、AtomicLong使用非常广泛 ,比如你的系统里面可能用到一些统计、计数场景 ,比如每秒访问的流量、注册中心每秒接收到注册的次数、心跳的次数 、可以使用这两个原子类。在一些开源的分布式系统、中间件系统 里面,大量的metric指标统计的功能都是基于AtomicInteger、AtomicLong这两个原子类去实现的,非常重要。
(2)AtomicBoolean 布尔类型的原子类
在多线程环境下我们使用基本的boolean 、Boolean 类型的布尔变量是非线程安全的,JUC提供类线程安全的布尔类型原子类AtomicBoolean。AtmoicBoolean 通常使用的场景是一些状态标识 ,比如初始化标识、系统关闭标识、逻辑状态判断标识、状态开关等等。
此外AtomicBoolean 还经常使用做非常轻量级的锁 ,比如阿里开源的分布式消息中间件RocketMQ就使用了AtomicBoolean封装了一个自旋锁 ,具有非常高的并发性能。(CAS将AtomicBoolean设置成true表示获取到了锁,释放锁的时候CAS操作将AtomicBoolean设置为false)
(3)AtomicReference、AtomicStampReference可以封装对象的原子类
上面的提供的AtomicInteger、AtomicLong、AtomicBoolean等都是基本类型对应的原子类;但是如果你共享的是一个对象呢?多个线程同时修改一个对象呢? 在不使用锁的场景下可以将对象使用AtomicReference进行包装,然后CAS的去修改对象,也可以达到线程安全的效果。
AtomicStampReference 则是AtomicReference的升级版本,提供版本号机制,解决CAS中经典的ABA问题
(5)LongAdder原子类
是AtomicLong原子类的一个升级版本 ,在并发竞争非常激烈 的时候可能会导致 大量的线程CAS失败而不断自旋 ,而LongAdder采用分段锁的思想 ,在并发竞争非常激烈的时候使得不同的线程去竞争不同的锁 ;这样就可以减少对同一个锁的竞争,优化了并发的性能。
小陈:哇塞,原子类还有这么多分类啊,厉害了...,老王啊,我们从哪里开始学,我等不及了,等我学完回去大展拳脚......
老王:小陈啊,我们本章的主题是概览,我们先大概了解一下Atomic的类体系、我们需要掌握哪些、分为哪些类等,具体的学习我们留到后面的讨论......
小陈:这样啊,那我先预习预习,明天等你来讲...
老王:好,本篇那就先到这里......
小陈:好的,我们下一章见。
目录
JAVA并发专题 《筑基篇》
4.什么是MESI缓存一致性协议?怎么解决并发的可见性问题?
JAVA并发专题《练气篇》
10.synchronized底层之monitor、对象头、Mark Word?
11.synchronized底层是怎么通过monitor进行加锁的?
12.synchronized的锁重入、锁消除、锁升级原理?无锁、偏向锁、轻量级锁、自旋、重量级锁
13.synchronized怎么保证可见性、有序性、原子性?
JAVA并发专题《结丹篇》
16.Atomic原子类体系讲解
17.AtomicInteger、AtomicBoolean的底层原理
18.AtomicReference、AtomicStampReference底层原理
19.Atomic中的LongAdder底层原理之分段锁机制
20.Atmoic系列Strimped64分段锁底层实现源码剖析
JAVA并发专题《金丹篇》
21.AQS是个啥?为啥说它是JAVA并发工具基础框架?
22.基于AQS的互斥锁底层源码深度剖析
23.基于AQS的共享锁底层源码深度剖析
24.ReentrantLock是怎么基于AQS实现独占锁的?
25.ReentrantLock的Condition机制底层源码剖析
26.CountDownLatch 门栓底层源码和实现机制深度剖析
27.CyclicBarrier 栅栏底层源码和实现机制深度剖析
28.Semaphore 信号量底层源码和实现机深度剖析
29.ReentrantReadWriteLock 读写锁怎么表示?
- ReentrantReadWriteLock 读写锁底层源码和机制深度剖析
JAVA并发专题《元神篇》并发数据结构篇
31.CopyOnAarrayList 底层分析,怎么通过写时复制副本,提升并发性能?
32.ConcurrentLinkedQueue 底层分析,CAS 无锁化操作提升并发性能?
33.ConcurrentHashMap详解,底层怎么通过分段锁提升并发性能?
34.LinkedBlockedQueue 阻塞队列怎么通过ReentrantLock和Condition实现?
35.ArrayBlockedQueued 阻塞队列实现思路竟然和LinkedBlockedQueue一样?
36.DelayQueue 底层源码剖析,延时队列怎么实现?
37.SynchronousQueue底层原理解析
JAVA并发专题《飞升篇》线程池底层深度剖析
- 什么是线程池?看看JDK提供了哪些默认的线程池?底层竟然都是基于ThreadPoolExecutor的?
39.ThreadPoolExecutor 构造函数有哪些参数?这些参数分别表示什么意思?
40.内部有哪些变量,怎么表示线程池状态和线程数,看看道格.李大神是怎么设计的?
-
ThreadPoolExecutor execute执行流程?怎么进行任务提交的?addWorker方法干了啥?什么是workder?
-
ThreadPoolExecutor execute执行流程?何时将任务提交到阻塞队列? 阻塞队列满会发生什么?
-
ThreadPoolExecutor 中的Worker是如何执行提交到线程池的任务的?多余Worker怎么在超出空闲时间后被干掉的?
-
ThreadPoolExecutor shutdown、shutdownNow内部核心流程
-
再回头看看为啥不推荐Executors提供几种线程池?
-
ThreadPoolExecutor线程池篇总结