JDK原子类基于CAS轻量级原子操作实现,使得程序运行效率变得更高。
(1)基本原子类
基本原子类的功能是通过原子方式更新Java基础类型变量的值。基本原子类主要包括以下三个:
AtomicInteger:整型原子类。
AtomicLong:长整型原子类。
AtomicBoolean:布尔型原子类。
(2)数组原子类
数组原子类的功能是通过原子方式更新数组中的某个元素的值。数组原子类主要包括了以下
三个:
AtomicIntegerArray:整型数组原子类。
AtomicLongArray:长整型数组原子类。
AtomicReferenceArray:引用类型数组原子类。
(3)引用原子类 保证对象引用的原子性
引用原子类主要包括以下三个:
AtomicReference:引用类型原子类。
AtomicMarkableReference:带有更新标记位的原子引用类型。
AtomicStampedReference:带有更新版本号的原子引用类型。
AtomicMarkableReference类将boolean标记与引用关联起来,可以解决使用AtomicBoolean进行原子方式的更新时可能出现的ABA问题。
AtomicStampedReference类将整数值与引用关联起来,可以解决使用AtomicInteger进行原子方式的更新时可能出现的ABA问题。
引用原子类测试
public class User implements Serializable { String uid; //用户ID String nickName; //昵称 public volatile int age; //年龄 public User(String uid, String nickName) { this.uid = uid; this.nickName = nickName; }
测试代码:
public class AtomicTest { @Test public void testAtomicReference() { //包装的原子对象 AtomicReference<User> userRef = new AtomicReference<User>(); //待包装的User对象 User user = new User("1", "张三"); //为原子对象设置值 userRef.set(user); Print.tco("userRef is:" + userRef.get()); //要使用CAS替换的User对象 User updateUser = new User("2", "李四"); //使用CAS替换 boolean success = userRef.compareAndSet(user, updateUser); Print.tco(" cas result is:" + success); Print.tco(" after cas,userRef is:" + userRef.get()); } }
首先创建了一个User对象,然后把User对象包装到一个AtomicReference类型的引用userRef中,如果要修改userRef的包装值,就需要调用compareAndSet()方法才能完成。该方法就是通过CAS操作userRef,从而保证操作的原子性。
使用原子引用类型AtomicReference包装了User对象之后,只能保障User引用的原子操作,对被包装的User对象的字段值修改时不能保证原子性,这点要切记。
(4)字段更新原子类:如果需要保障对象某个字段(或者属性)更新操作的原子性,需要用到属性更新原子类
字段更新原子类主要包括以下三个:
AtomicIntegerFieldUpdater:原子更新整型字段的更新器。
AtomicLongFieldUpdater:原子更新长整型字段的更新器。
AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
要求:
第一步,更新的对象属性必须使用public volatile修饰符。
第二步,因为对象的属性修改类型原子类都是抽象类,所以每次使用都必须使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新的类和属性。
同时可以减少内存
字段更新原子类测试:继续基于上面的User类测试
public void testAtomicIntegerFieldUpdater() { //使用静态方法newUpdater()创建一个更新器updater AtomicIntegerFieldUpdater<User> updater= AtomicIntegerFieldUpdater.newUpdater(User.class, "age"); User user = new User("1", "张三"); //使用属性更新器的getAndIncrement、getAndAdd增加user的age值 Print.tco(updater.getAndIncrement(user)); // 1 Print.tco(updater.getAndAdd(user, 100)); // 101 //使用属性更新器的get获取user的age值 Print.tco(updater.get(user)); // 101 }
运行以上代码,结果如下:
[main]:0
[main]:1
[main]:101
实际应用:
标签:引用,更新,原子,userRef,user,多线程,User From: https://www.cnblogs.com/clarino/p/18624048