本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Atomic类
简述常见的Atomic类
在很多时候,我们需要的仅仅是一个简单的、高效的、线程安全的++或者--方案,使用synchronized关键字和lock固然可以实现,但代价比较大,此时用原子类效率更高。
(1)基本数据类型的原子类有:
AtomicInteger 原子更新整形、AtomicLong 原子更新长整型、AtomicBoolean 原子更新布尔类型
(2)Atomic数组类型有:
AtomicIntegerArray 、AtomicLongArray AtomicReferenceArray 原子更新数组里的元素。
(3)Atomic引用类型有
AtomicReference 原子更新引用类型
AtomicMarkableReference 原子更新带有标记位的引用类型,可以绑定一个 boolean 标记
AtomicStampedReference 原子更新带有版本号的引用类型
Atomic类基本实现原理
以AtomicIntger 为例:
getAndIncrement()方法:以原子方式将当前的值加1,具体实现为:
- 在 for 死循环中取得 AtomicInteger 里存储的数值
- 对 AtomicInteger 当前的值加 1
- 调用 compareAndSet 方法进行原子更新
- 先检查当前数值是否等于 expect
- 如果等于则说明当前值没有被其他线程修改,则将值更新为 next,
- 如果不等于则更新失败返回 false,程序会进入 for 循环重新进行 compareAndSet 操作。
CAS
Compare And Swap,是CPU为了解决并发问题而提供的指令;
该指令包含三个参数: 1.共享变量的内存地址A; 2.用于比较的值B; 3.共享变量的新值C;
当且仅当地址A处的值等于B时,才将地址A处的值更新为C;
自旋
使用CAS解决并发问题,通常要采用自旋操作;
所谓自旋就是循环尝试,即本次操作不成功则自动进入下-轮尝试;
ABA
判断相等不代表该值未被更新过(A->B->A) ;
若为基本类型可以忽视该问题,若为引用对象则需要进行检查;
ReadWriteLock
场景:适合读多写少的场景;
原则:1.允许多个线程同时读共享变量;
2.只允许一个线程写共享变量;
3.如果一个线程正在执行写操作,此时禁止其他线程读共享变量;
实现:ReentrantReadWriteLock,是读写锁,也是可重入锁,并且可以是公平的/非公平的;
CopyOnWrite
CopyOnWriteArrayList, CopyOnWriteArraySet;
修改时,容器会复制出一个新数组,在新数组上完成修改后再替换掉旧数组;