1 . 什么是JUC?
JUC就是java.util.concurrent包,这个包俗称JUC,里面都是解决并发问题的一些东西,它的基础 AQS。
JUC中的4大常用并发工具类:
CountDownLatch
CyclicBarrier
Semaphore
ExChanger
2. 常用的JUC下的原子操作类
更新基本类型类:AtomicBoolean,AtomicInteger,AtomicLong
更新数组类:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
更新引用类型:AtomicReference,AtomicMarkableReference,AtomicStampedReference
更新字段类: AtomicReferenceFieldUpdater,AtomicIntegerFieldUpdater,AtomicLongFieldUpdater
重点: LongAdder
LongAdder是JDK1.8新增的一个工具类,考虑到AtomicLong使用CAS更新value值在高并发下会有大量的线程CAS失败,从而导致自旋,消耗CPU资源。
LongAdder的思想是将一个value打散成多个Cell数组,每个Cell维护一个value,当存在多线程并发操作的时候,将线程映射到一个Cell上进行操作,每个Cell内的value值还是使用CAS更新,就这样将竞争分散到多个Cell中。同时,如果没有出现多线程竞争,那么直接操作提供的一个base字段,换句话说就是先通过CAS修改base字段,如果CAS失败,那么转去修改Cell。最后获取值的时候,即使把base和所有cell相加。假设CAS修改base失败,那么可能是下面这样:
Cell并不是一开始就创建的,而是出现竞争,也就是CAS操作base失败的时候才会创建(lazy),初始创建大小为2,每次扩容成原大小的2倍,扩容直到大小为CPU可用的逻辑内核数量(通过Runtime获取)即停止。同时,Cell数组初始化、数组元素初始化、扩容等时候需要做同步处理,而同步处理的操作不是加锁,而是对int类型的cellsBusy字段做CAS操作,cellsBusy有0和1两个值,CAS就是尝试将0修改为1,如果修改成功,那么可以执行逻辑,之后会将其设置回0,这个类似于ReentrantLock利用state字段的加锁逻辑。
LongAdder继承自Striped64,前面提到的Cell是Striped64的一个静态内部类,base、Cell数组、cellsBusy等都定义在Striped64类中。
应用:concurrentHashMap