首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

一文总结Java中原子类相关实现

开发中涉及到公共资源如果都可以用锁去控制并发,但是对于简单比如一个变量都要实现一个并发控制难免太复杂了,所以Java提供了一些简单的原子类以供使用。

基础原子类

最基础的原子类主要有三个AtomicInteger、AtomicBoolean、AtomicLong,这三个类作为一些简单的公关资源或者开关等已经能够满足需求了,他们的实现都比较简单,。首先是AtomicBoolean他维护一个volatile修饰的int型变量value,(volatile作用关键字不清楚可以去了解下,简单说下就是能够保证内存可见性,也就是一个线程修改了其他线程能够马上看到)value等于1表示true等于0表示false,AtomicBoolean提供compareAndSet、getAndSet、get等方法,get方法返回value是否等于1的判断结果,compareAndSet利用Unsafe(这个类是Java并发很关键的类各种原子操作都靠它)来修改value的值,修改成功返回true,修改失败返回false,getAndSet通过循环get与compareAndSet操作,当compareAndSet成功是返回get的值,也就能保证获取到这次修改前的值。

AtomicInteger也维护一个一样的value,提供了addAndGet、getAndAdd、getAndDecrement等系列方法,addAndGet返回的是修改后的值,getAndAdd返回的是修改前的值。AtomicInteger只提供了简单的加减法,不过也提供了accumulate类方法,可以自己定义一些计算,比如除法,平方之类的。

AtomicLong与AtomicInteger提供的差不多,区别在于AtomicLong维护的value是long类型,主要的是Unsafe的long相关修改方法。

这三个类原子都是在内部保存一个变量value,并且通过volatile关键字修饰保证数据的可见性。然后依赖Unsafe的CAS方法保证并发修改的正确性,再综合利用volatile与Unsafe的CAS方法返回结果组合使用利用循环保证更新线程安全和一定成功。

数组类型原子类

数组类型原子类也有三个AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray,AtomicIntegerArray与AtomicLongArray实际上和AtomicInteger与AtomicLong提供的功能差不多,只不过他们是提供一个数组的原子性,也就是他们提供的是一系列变量的原子性,而AtomicInteger与AtomicLong维护的是一个变量的原子性。

而AtomicReferenceArray与AtomicReference就和AtomicIntegerArray与AtomicInteger对比一样。

他们与单个原子类的区别是,再初始化的时候会初始化一个数组,每次修改都是修改指定数组索引的一个数据。逆向思维一下就相当于他们是在维护一个数组的原子性,而基础原子类是在维护单个变量的原子性。

引用类型原子类

引用类型的原子类也有三个AtomicReference、AtomicStampedReference、AtomicMarkableReference,主要是AtomicReference介绍下,另外两个原子类都是对AtomicReference的扩展,但是实际上AtomicReference和基础原子类一样,甚至我觉得可以归为基础类,因为它和基础类一样是维护一个变量value只不过类型是泛型,也就是说可以保存任意的类型,然后每次修改的时候比较value的引用是否一致。所以AtomicReference相当于是基础类型的扩展,它是维护所有对象,每次修改的时候都需要验证value的引用而基础类型是验证具体的值

AtomicStampedReference是对 AtomicReference 的升级,它的实现是维护一个volatile 修饰的Pair类型变量,Pair保存有需要维护的对象和一个int类型的标记(就好像版本号),每次更新都是创建一个新的Pair对象,所有每次修改都要对象和标记同时满足才能成功,解决 CAS 的 ABA 问题。

AtomicMarkableReference与AtomicStampedReference类似,只不过Pair类中维护的表示是boolean类型,可以用于表示该对象已删除等场景

字段更新器

有一些对象已经发布出去了无法修改,但是可能一开始的设计并没有考虑线程安全问题,现在再做修改要保证它其中一些属性的线程安全就可以利用字段更新器,主要有三个类AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater,提供的主要功能和AtomicInteger、AtomicLong、AtomicReference一样,只不过AtomicIntegerFieldUpdater是维护指定对象的指定属性的线程安全,AtomicInteger是维护它自己的value的线程安全的区别

总结

原子类提供的功能还是比较简单的,源码也是比较简单的,都是利用Unsafe对一个对象的属性进行线程安全的修改,FieldUpdater系列原子类维护的是指定对象的指定属性,而其他系列原子类维护的是自己的一个属性的线程安全。简单对比如下图:

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200823A0KMW500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券