一、原子数组
有些改变的不只是共享变量的引用,而是更改所引用对象的内部数据。
比如共享变量是一个数组,不想改数组的地址,而是想改数组的内部数据,同时保证更改的过程是原子性的,是线程安全的,故引入原子数组。
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray
如果非原子数组由1000个线程同时更改,会出现线程安全问题
import java.util.concurrent.atomic.AtomicIntegerArray;import java.util.concurrent.atomic.AtomicMarkableReference;import java.util.concurrent.atomic.AtomicReference;import java.util.concurrent.atomic.AtomicStampedReference;public class Test{public static void main(String[] args) throws InterruptedException {ArrayTest arrayTest = new ArrayTest();for(int i=0;i<10000;i++){new Thread(()->{arrayTest.incerementIntegerArray();}).start();}Thread.sleep(2000);//主线程等待两秒后//打印数组for (int i=0;i<10;i++){System.out.println(arrayTest.getIntegerArray()[i]);}}}class ArrayTest{private int[] integerArray;//数组public int[] getIntegerArray() {return integerArray;}public void setIntegerArray(int[] integerArray) {this.integerArray = integerArray;}public ArrayTest(){this.integerArray =new int[10];//创建一个大小为10的数组}public void incerementIntegerArray(){for(int i=0;i<integerArray.length;i++){integerArray[i]++;}}}
结果如下:

二、原子更新器
原子更新器又叫做字段更新器,利用字段更新器,可以针对对象的某个域(Field)进行原子操作,当多线程访问同一对象(共享资源)时,保证了对象某一成员变量的线程安全性。只能配合 volatile 修饰的字段使用,否则会出现异常
Exception in thread "main" java.lang.IllegalArgumentException: Must be volatile type
- AtomicReferenceFieldUpdater //域 字段,表示字段是引用类型的
- AtomicIntegerFieldUpdater //表示字段是整型的
- AtomicLongFieldUpdater //表示字段是long型的
import java.util.concurrent.atomic.*;public class Test{public static void main(String[] args) {Student stu = new Student();//创建共享变量Student类对象/** 保护某类的某个属性,设置为原子属性* 参数分别指定:保护的类、保护的属性、属性的名字** */AtomicReferenceFieldUpdater updater = AtomicReferenceFieldUpdater.newUpdater(Student.class,String.class,"name");//接着再拿updater对象操作保护的属性即可,多线程环境下updater.compareAndSet(stu,null,"张三");//stu为访问的共享对象,null是期待值,“张三”是修改值}}class Student{String name;@Overridepublic String toString() {return super.toString();}}
