本文主要内容
1、原子操作定义
2、原子操作的方式(同步锁机制、cas机制、原子操作类)
3、总结
一、原子操作定义
1、定义:
原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而执行其中的一部分,原子操作具有不可中断性。它的核心特征是将整个操作视为一个整体。
2、实例:
上面的截图中i++操作存在多个操作,在多线程环境下会出现竞态条件,线程不安全,需要转变为原子操作才能安全。下面将介绍操作操作的方式。
二、原子操作方式
1、同步锁机制:
2、cas机制
定义:cas机制:cas操作需要输入两个数值,一个旧值A和一个新值B,在操作期间先比较下旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。
java中sun。misc。Unsafe类提供了一些方法实现cas。
实例:
3、原子操作封装类
(1)基础版: Java中提供了一些原子操作封装类,封装了cas机制的底层代码,使得用户使用起来更加方便。
例如:
AtomicBoolean:原子更新布尔类型;AtomicInteger:原子更新整型;AtomicLong:原子更新长长整型。
AtomicIntegerArray:原子更新整型数组里的元素。 AtomicLongArray:原子更新长整型数组里的元 素。 AtomicReferenceArray:原子更新引用数组里的元素。
AtomicIntegerFieldUpdater:原子更新整型字段里的更新器。 AtomicLongFieldUpdater:原子更新长整型字段里的更新器。 AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
AtomicReference:原子更新引用类型。 AtomicStampedReference:原子更新带有版本号的引用类型。 AtomicMarkableReference:原子更新带有标记位的引用类型。
实例:下面介绍AtomicInteger类的实例
(2)更新版: 1.8版本的jdk还更新了四个原子操作的封装类。
更新器:DoubleAccumulator、LongAccumulator
计数器:DoubleAdder、LongAdder
实例1:介绍LongAccumulator类使用代码
实例2:下面是LongAdder类的使用代码
计数器增强版,高并发下性能更好,频繁更新但不太频繁读取的汇总统计信息时使用,分成多个操作单元,不同线程更新不同的单元,只有需要汇总的时候才计算所有单元的操作
三、总结
cas的弊端:
1、cpu开销大,在高并发下,许多线程,更新一变量,多次更新不成功,循环反复,给cpu带来大量压力。
2、只是一个变量的原子性操作,不能保证代码块的原子性。
3、ABA问题
ABA问题:内存值V=100;
threadA 将100,改为50;
threadB 将100,改为50;
threadC 将50,改为100;
场景:小牛取款,由于机器不太好使,多点了几次全款操作。后台threadA和threadB工作,
此时threadA操作成功(100->50),threadB阻塞。正好牛妈打款50元给小牛(50->100),
threadC执行成功,之后threadB运行了,又改为(100->50)。
牛气冲天,lz钱哪去了???
如何解决aba问题:
对内存中的值加个版本号,在比较的时候除了比较值还的比较版本号。
java:AtomicStampedReference就是用版本号实现cas机制。