本文共 1548 字,大约阅读时间需要 5 分钟。
CAS 是英文单词 Compare And Swap 的缩写,翻译过来就是比较并替换。 CAS机制当中使用了 3 个基本操作数:内存地址 V ,旧的预期值 A ,要修改的新值 B 。 更新一个变量的时候,只有当变量的预期值A 和内存地址 V 当中的实际值相同时,才会将内存地址 V 对应的值修改为B 。 synchornized(内置锁)从思想上来说是属于
悲观锁,悲观地认为程序中的并发情况严重,所以使用数据之前先加锁即严防死守。而CAS机制属于
乐观锁,乐观地认为程序中地并发情况不那么严重,所以让线程不断地去尝试更新。
CAS中地比较和交换过程(自旋地过程) 优点:在并发量不高地情况下可以避免线程地阻塞,从而可以提高效率。
缺点:
- 自旋(循环)过程开销大。
- 只能保证单独共享变量地原子操作。
- ABA问题
原子操作类在实际开发应用中用的并不是太多,故引用<java并发编程的艺术>中的部分内容
atomic包提供原子更新基本类型的工具类:
- AtomicBoolean: 以原子更新的方式更新boolean。
- AtomicInteger: 以原子更新的方式更新Integer。
- AtomicLong: 以原子更新的方式更新Long。
以AtomicInteger为例总结常用的方法:
- addAndGet(int delta) :以原子方式将输入的数值与实例中原本的值相加,并返回最后的结果;
- incrementAndGet() :以原子的方式将实例中的原值进行加1操作,并返回最终相加后的结果;
- getAndSet(int newValue):将实例中的值更新为新值,并返回旧值;
- getAndIncrement():以原子的方式将实例中的原值加1,返回的是自增前的旧值;
atomic包下提供能原子更新数组中元素的类有:
- AtomicIntegerArray:原子更新整型数组中的元素;
- AtomicLongArray:原子更新长整型数组中的元素;
- AtomicReferenceArray:原子更新引用类型数组中的元素
以AtomicIntegerArray来总结下常用的方法:
- addAndGet(int i, int delta):以原子更新的方式将数组中索引为i的元素与输入值相加;
- getAndIncrement(int i):以原子更新的方式将数组中索引为i的元素自增加1;
- compareAndSet(int i, int expect, int update):将数组中索引为i的位置的元素进行更新
如果需要原子更新引用类型变量的话,为了保证线程安全,atomic也提供了相关的类:
- AtomicReference:原子更新引用类型;
- AtomicReferenceFieldUpdater:原子更新引用类型里的字段;
- AtomicMarkableReference:原子更新带有标记位的引用类型;
如果需要更新对象的某个字段,并在多线程的情况下,能够保证线程安全,atomic同样也提供了相应的原子操作类:
- AtomicIntegeFieldUpdater:原子更新整型字段类;
- AtomicLongFieldUpdater:原子更新长整型字段类;
- AtomicStampedReference:原子更新引用类型,这种更新方式会带有版本号。而为什么在更新的时候会带有版本号,是为了解决CAS的ABA问题;
要想使用原子更新字段需要两步操作:
- 原子更新字段类都是抽象类,只能通过静态方法
newUpdater
来创建一个更新器,并且需要设置想要更新的类和属性; - 更新类的属性必须使用
public volatile
进行修饰;
转载地址:http://kfuqb.baihongyu.com/