本文共 1613 字,大约阅读时间需要 5 分钟。
原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分(不可中断性)。将整个操作视作一个整体,资源在该次操作中保持一致,这是原子性的核心特征。
Compare and swap 比较和交换。属于硬件同步原语, 处理器提供了基本内存操作的原子性保证。
CAS操作需要输入两个数值,一个是旧值A(期望操作前的值)和一个新值B,在操作期间先对旧值进行比较,若没有发生变化,才交换成新值,发生了变化则不变换。
JAVA中的sun.misc.Unsafe
类,提供了compareAndSwapInt()
和compareAndSwapLong()
等几个方法实现CAS。
在进行CAS操作的时候要对需要更新的变量用volatile修饰。
AtomicBoolean
:原子更新布尔类型AtomicInteger
:原子更新整型AtomicLong
:原子更新长整型AtomicIntegerArray
:原子更新整型数组里的元素AtomicLongArrary
:原子更新长整型数组里的元素AtomicReferenceArray
:原子更新引用类型数组里的元素AtomicIntegerFieldUpdater
:原子更新整型的字段的更新器AtomicLongFieldUpadter
:原子更新长整型字段的更新器AtomicReferenceFieldUpdater
:原子更新引用类型里的字段AtomicReference
:原子更新引用类型AtomicStampedReference
:原子更新带有版本号的引用类型AtomicMarkableReference
:原子更新带有标记为的引用类型AtomicInteger等类的底层就是利用CAS机制实现
计数器增强版,高并发下性能更好。
DoubleAccumulator、LongAccumulator
DoubleAdder、LongAdder
原理:分成多个操作单元,不同线程更新不同的单元只有需要汇总的时候才计算所有单元的操作。
场景:高并发频繁更新、不太频繁地读取。
JDK提出了高并发场景性能更好的累加计数器
会对链表的操作产生很大的影响,在两个线程操作的时候thread 1 和thread 2同时对一个链表进行操作之后,可能会导致原有的链表表头指向了其他节点,使得thread 2操作产生问题
原链表是A-B,thread 2先对链表中表头A进行操作,将C,D连上A节点,然后thread 1又对链表中表头A进行操作,又将A指向了B。操作失效。还会对栈造成影响,造成栈失效,和链表问题类似,只要指向的那个节点还在,就会对后续进行操作,产生A B A问题。
栈顶一开始指向A-B,然后thread 2对栈进行操作,弹出A-B,压入B-C-D-A,然后thread 1又对线程进行操作,thread 1中A又会指向B,会让C-D失效。解决方案: 用版本号进行修饰,匹配版本号来确定原数据是否被修改过。带有版本号的数字引用类型,可以实现版本号锁
转载地址:http://rmugn.baihongyu.com/