原子操作CAS
一、什么是原子操作
不可被中断的一个或者一系列操作、
CAS是Compare And Set的缩写,是以一种无锁的方式实现并发控制。在实际情况下,同时操作同一个对象的概率非常小,所以多数加锁操作做的是无用功,CAS以一种乐观锁的方式实现并发控制。
二、实现原子操作的方式
Java可以通过锁和循环CAS的方式实现原子操作。
三、CAS( Compare And Swap ) 为什么要有CAS?
Compare And Swap就是比较并且交换的一个原子操作,由Cpu在指令级别上进行保证。
为什么要有CAS:因为通过锁实现原子操作时,其他线程必须等待已经获得锁的线程运行完以后才能获得资源,这样就会占用系统的大量资源
四、CAS包含哪些参数?
CAS包含三个参数:1、变量所在内存地址V;2、变量对应的值A;3、我们将要修改的值B。如果说V上的变量的值是A的话,就用B重新赋值,如果不是A,那就什么事也不做,操作的返回结果原值是多少。
循环CAS:在一个(死)循环【for(;;)】里不断进行CAS操作,直到成功为止(自旋操作即死循环)。
五、CAS的原理
利用了现代处理器都支持的CAS的指令,循环这个指令,直到成功为止
六、CAS实现原子操作的三大问题
1、 ABA问题:其他的线程把值改成了B,很快改成了A,原子操作的线程发现值是A就修改,这样会有问题。解决ABA,引入版本号:1A-》2C-》3A
2、 循环时间很长的话,cpu的负荷比较大
3、 对一个变量进行操作可以,同时操作多个共享变量有点麻烦
七、CAS线程安全(面试点)
通过硬件层面的阻塞实现原子操作的安全
八、原子操作类
jdk提供了许多根据CAS思路产生的原子操作类;总结下来可以分成以下几类:
更新基本类型类:AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference
更新数组类:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
更新引用类型:AtomicReference,AtomicMarkableReference,AtomicStampedReference
原子更新字段类: AtomicReferenceFieldUpdater,AtomicIntegerFieldUpdater,AtomicLongFieldUpdater
例子:我们只是看其中的及格就行了
AtomicInteger (这里我们要注意incrementandget()和getAndincrement())
package pers.cc.cas; import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest { /** * 定义一个线程安全的Integer并设定初始值为0 */ static AtomicInteger atomicInteger = new AtomicInteger(0); static int i = 0; public static void main(String[] args) throws InterruptedException { for (int j = 0; j < 100000; j++) { Thread addThread = new Thread(new Runnable() { @Override public void run() { // 原子的增加1 atomicInteger.incrementAndGet(); i++; } }); addThread.start(); } Thread.sleep(2000); System.out.println(atomicInteger.get()); System.out.println(i); } }
运行结果:
100000 99998
AtomicMarkableReference() 和 AtomicStampedReference()--区别?
--一个是通过版本号,一个是通过boolean值
参考文章: