概念:
CAS(比较并且交换)是无锁优化,或者叫自旋,还有自适应自旋,我们通过Atomic类(原子的)。常常配合循环使用,由于这些操作,老是来回的加锁,减锁,加锁情况特别多,我们java提供了这样常见操作的一个类,这些类的内部就自动带了锁,这些锁不是synchronized重量级锁,而是CAS操作来实现(无锁)。
凡是以Atomic开头的类都是用CAS来保证线程安全的。AtomicInteger里面包装了
int类型,这个int类型的count++操作是线程安全的,还有拿值等等是线程安全
的。工作开发中经常会有一个值所有的线程共同访问他往上递增。如何使用AtomicI
nteger,如下图代码,AtomicInteger用法:
那么cas的内部实现的原理是什么呢?AtomicInteger类的incrementAndGet()调用了Unsafe类的getAndAdddInt()方法,下图是源码的实现:
当然了,这也属于一个CompareAndSetInt()操作,比较并且设定。
我原来想改变某一个值0,我想把它变成1,但是我想线程安全,就必须加synchroni
zed,现在我可以用另外一种操作代替这把锁,那就是cas操作,把它想象成一个方法
cas(V,expected,NewValue)。
V:要修改的值。
expected:期望值。期望会是几。
NewValue:要设定的新值。
比方说:当前的这个线程想改这个值,我期望你是0,你就不能是1;如果是1,那就
说明我这个值不对,然后想把你变成1。大概就是:原来这个值是变为3了,我这个线
程想修改这个值的时候我一定期望你现在是3,是3我才改,如果在我修改的过程你变
4了,说明就有另外一个线程修改过该值,那我cas就再重新试一下,再试的时候,
我希望你的这个值是4,在修改的时候期望值是4,没有其它线程修改该值,那好我
给你改成5,这样就是cas操作。
当你判断的时候,发现是我的期望值,还没有进行新值设定的时候值发生了改变怎么办,cas是cpu的原语支持,也就是说cas是cpu指令级别上的支持
中间不能被打断。这就是cas的一些知识,望对大家有点帮助。
二:cas的一个ABA问题:
假如说你有一个值,我拿到这个值是0,想把它变成2,我拿到1用cas操作,期望值是
1,准备变成2,对象是Object,在这个过程中没有一个线程改过我这个值,肯定可
修改。如果有一个线程在这个过程中把这个1修改成了2后来又变回1,中间值更改过
但是不影响我后面的操作,这就是ABA问题。
如何解决这个问题呢?
如果是int类型的,最终值是你期望的。没有关系。确实想要解决的话,就是加版本,做任何一个值的修改,修改完加一,后面检查的时候连同版本号一起检查。