有了AtomicInteger、AtomicReference(引用类型)、AtomicStampReference(引用类型加了时间戳)之后,再说一下关于数组的atomic的使用
1、AtomicIntegerArray
这是一个数组的atomic,它的方法类中一共有这些方法

数组中的每一个元素都是线程安全的
这里通过了一个小的demo来做演示

运行之后,看到的结果为

这样就保证了每个元素的线程安全、
这里重点讲解下AtomicIntegerArray这个类

这里面定义了这么一个普通的数组,在看看这个类中的get方法

这里面调用了这个getRaw的这个方法

这个方法的意思是获取以array为基础,然后以offset为偏移量的数据

而这个方法的意思是,获取第i个下标元素对应的偏移量是多少
这里通过了byteOffset的方法来算

其中的这个base为数组所在的基地址

就这个数组所在的base基地址(所谓的数组的第一个元素)开始,然后往后取值,如果是int类型的话,就取4个byte位
而在上面的方法中就是i偏移了shift的长度,那shift的长度是多少呢

这里用到了数据的numberOfLeadingZeros(前倒零)的操作
这里说一下什么是前倒零

如果说是int,4个字节(byte),二进制的话就是100,因为整数是32位的,那么100前面的29个0就是LeadingZeros(前倒零)

这个操作就是数组中的其中一个元素有多宽,如果是int型的话,那么就是4个字节,那么这时的scale就是一个4,那么

Integer.numberOfLeadingZeros(scale),这里取4的前倒零的话就是29,那么shift=31-29=2
所以上面的操作就是((long) i << 2) + base,其实如果说是int的话也相当于base+4,之所以用i<<2的形式的话,也是为了增加一点性能,jdk中也大量使用了位移符的运算
(i<<2相当于是i以二进制的形式往后添加2个0,二进制的话i<<2等于i*100,十进制的话i<<2等于i*4)
2、AtomicIntegerFieldUpdater
这个方法的作用在于让普通的变量也享有原子性,应用场景是:比如说定义了一个int类型,如果在后期的维护上想要把这个变量变成CAS的操作的话,就可以使用这个方法
这个方法里面有一个newUpdate(),这是新建一个通过工厂方法实现的更新器,用increnmenAndGet()来做更新,这里的话有写一个demo

首先要注意的是,不是对原变量一点也不去做修改,而是在原变量的基础上添加一个volatile的修饰符,这样的改变不会影响到其他的地方对这个变量的使用,改动相对较小,接着创建一个Candidate的对象,使用更新器来更新这个对象,然后,通过scoreUpdater.incrementAndGet(stu)来对这个对象做递增操作,这里底层使用了反射的机制来实现的,最后再打印出累加的结果


最后,可以发现和用atomic修改的变量一样是线程安全的




