Atomic*系列原子类相关知识

   日期:2020-08-27     浏览:76    评论:0    
核心提示:文章目录Atomic*特点Atomic*系列包括Atomic*缺点参考Atomic*特点Atomic* 按锁的类型来区分应该是属于乐观锁,就是多个线程在读取使用变量的时候是互不影响,非阻塞式的。sun.misc.Unsafe里面包含了大量的C代码和多种直接操作内存和原子能力的方法,所以被标记为不安全的,Atomic*系列主要就是使用了这个类的能力,来实现了非阻塞时的线程安全。Unsafe是一个非对外的类,内部是采用了单例模式来实现的,如果需要使用的话,可以通过反射的方式获取Unsafe内部的theU

文章目录

      • Atomic*特点
      • Atomic*系列
      • Atomic*缺点
      • 参考

Atomic*特点

  1. Atomic* 按锁的类型来区分应该是属于乐观锁,就是多个线程在读取使用变量的时候是互不影响,非阻塞式的。
  2. sun.misc.Unsafe里面包含了大量的C代码和多种直接操作内存和原子能力的方法,所以被标记为不安全的,Atomic*系列主要就是使用了这个类的能力,来实现了非阻塞时的线程安全。Unsafe是一个非对外的类,内部是采用了单例模式来实现的,如果需要使用的话,可以通过反射的方式获取Unsafe内部的theUnsafe成员变量,从而获取Unsafe的实例。
    boolena success = U.compareAndSwap*(obj, argAddrOffset, expectValue, updateValue)
    
    • Unsafe类中包含了大量compareAndSwap* 的方法,支持int、long、object、array等类型,参数都是类似的。
    • obj指的是要修改的变量所在的类地址,也就是起始内存地址,数组则对应第一个元素的内存地址;
    • argAddrOffset指的是基于obj的地址,需要偏移的地址,即待修改的变量地址=obj的起始地址+argAddrOffset,数组则直接对应下表,UnSafe这个类中有大量的方法可以获取某个变量的偏移量地址,如成员变量使用objectFieldOffset方法获取变量偏移量,静态变量使用staticFieldOffset方法获取变量便宜量;
    • expectValue指的是期望的值,即上一次读取到该线程工作内存中的值,如果两个值一致,则说明变量没有被修改,即可以直接将updateValue的值更新到主内存,否则更新失败,需要注意的是,这个比较和更新的动作是原子的,都JVM底层定义的原子操作来保证其原子性;
    • updateValue指的是待更新到主内存中的值。
    • 返回值为true则说明更新成功,返回false则说明更新识别,有可能是其他的线程更细了这个值
    U.getAnd*(obj,argAddrOffset,value)
    
    • 获取并做某些处理,可以是增加也可以是替换,如getAndAddInt()、getAndSetInt()等,返回的值都是修改之前的值,并且这些操作都是源自的操作,有JVM底层来保证。
  3. UnSafe类只提供了先获取再更新的方法,所以Atomic中提供的更新再获取的方法都是上层基于getAnd方法自定义逻辑来做的。
  4. Atomic*通过UnSafe来保证原子性,通过使用volatile来修饰value变量从而保证可见性,从而达到了我们的目的。

Atomic*系列

  • AtomicInteger
  • AtomicBoolean【底层是通过AtomicInteger来实现的,通过0-false,1-true来表示】
  • AtomicLong
  • AtomicReference

都是用原子的方式来更新指定类型的值

  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReferenceArray

可以直接操作数组的某个元素的值,保证更改元素的原子性,另外所有的array都是经过一次clone后才存储到Atomic*中的

  • AtomicIntegerFieldUpdater
  • AtomicLongFieldUpdater
  • AtomicReferenceFieldUpdater

可以修改某些类的成员变量,前提是这个类的变量是非静态的,且是非final的,可访问的

  • AtomicMarkableReference
  • AtomicStampedReference

添加了版本号的原子类,可以用来解决ABA问题,Markable只支持true、false两种状态,stamped支持多种状态

  • DoubleAccumulator
  • DoubleAdder
  • LongAccumulator
  • LongAdder

jdk1.8增加的新特性,主要是增加了吞吐量,但不能替代Atomic*系列

Atomic*缺点

  • 当线程之间存在激烈的竞争时,容易出现某个线程长时间无法插入数据,从而导致多次循环,浪费CPU资源的情况。
  • 同时采用普通的CAS来保证数据的安全,还容易出现ABA的问题,即某个数据从一个初始状态,经过多个状态变化后又回到初始状态,却被当做该数据是没有被更改过,这种情况在某些业务场景中是有问题的,这种问题可以通过采用带版本号的修改的方式来解决,即给每一次修改都添加一个版本。

参考

Java JUC之Atomic系列12大类实例讲解和原理分解
线程安全性详解(原子性、可见性、有序性)

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服