当程序更新一个变量的时候,如果多线程同时更新这个变量,可能得到期望之外的值,我们在jmm内存模型中https://www.jianshu.com/writer#/notebooks/40095376/notes/65884552提到的volatile,解决内存可见性以及禁止指令重排序,但是解决不了线程安全问题,通常我们会用synchronized解决,悲观锁保证了线程不会同时更新,可能会造成线程阻塞,CAS算法也就是Compare and swap(比较交换)是一种乐观锁,原子操作类运用的CAS算法解决线程变量的不安全问题,简单性能高效的更新变量的方式。
CAS算法的核心是:读取原先的值V,预估现在的值A,即将更新的值B,如果V等于A那么就将B更新,否则不进行更新。
在jdk 1.5 引进了并发工具包concurrent,其中有一个包名为atomic的包,包含了几种常用的原子类

从上图我们可以看到atomic包中包含的类:原子更新布尔类型,原子更新整型,原子更新长整型。原子更新整型数组,原子更新长整型数组,原子更新引用类型数组,原子更新饮用类型,原子更新引用类型里面的字段(含field的类),原子更新都有标记位的引用类。主要包含的这些,大体可以根据英文名字对应上。并且像原子更新布尔,整型,和长整型使用上都一样,数组这款也一样的核心,引用类型的更新我们一会看一个例子,同样的核心方法我们就举例的时候只举一类。
我们知道一个i++操作底层分为三步:将i读取出来放入临时变量,对i的值进行加1更改,然后最后一步就是将临时变量赋值给i。

当然我们用synchronized可以解决以上问题,那么我们今天用AtomicInteger这个类


这里面有一个方法ai.getAndSet(0,3),如果把第12行去掉大家看下13行应该打印什么?答案是1,打印的原先的值,在声明ai的时候是将value中的数据copy进ai中去的,所以应该打印原先的1。

AtomicReference原子引用类可改变引用对象的值。

AtomicIntegerFieldUpdater改变指定对象的某个值,但是这个指定要改变的对象的字段需要加上volatile才可以使用,也就是old 这个字段需要加上volatile,保证线程的可见性。因为原子更新字段类都是抽象类,每次使用的时候必须使用静态方法newUpdater()创建一个更新期,并且需要设置想要更新的类和属性。
1)在上述的例子中,对于字段old的修改,其中old的修饰必须是基本类型数据,用volatile修饰,不能是包装类型,int,long就可以,但是不可以是Integer和Long;2) 必须是实例变量,不可以是类变量;3) 必须是可变的变量,不能是final修饰的变量