Atomic*系列原子类相关知识

文章目录Atomic*特点Atomic*系列Atomic*缺点参考

Atomic*特点

    Atomic* 按锁的类型来区分应该是属于乐观锁,就是多个线程在读取使用变量的时候是互不影响,非阻塞式的。
    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底层来保证。

    UnSafe类只提供了先获取再更新的方法,所以Atomic中提供的更新再获取的方法都是上层基于getAnd方法自定义逻辑来做的。
    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【与LongAccumulator类型,只是类型变成了Double】
DoubleAdder【与LongAdder类型,只是类型变成了Double】
LongAccumulator【比LongAdder强大,支持只定义base的初始值,以及自定义累计方式,LongAdder相当于是base为0和累计方式固定为相加的LongAccumulator】
LongAdder【相当于是LongAccumulator的一个特例,base为0的特例】

jdk1.8增加的新特性,主要是增加了吞吐量,主要是通过在cas冲突时采用变量数组Cell[]的方式来将该线程待更新的值先更新到数组的其他位置,有点类似ConcurrentHashMap中的分段锁的概念,他们都有一个通病:由于在内部没有加锁,所以在多线程中调用sum和reset等方法,会出现不精确的问题,但是在单线程中调用是正确的,该类型的变量可以用在统计类似点击量和浏览量等并发高,但不要求精确的场景中,不能替代Atomic*系列

Atomic*缺点

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

参考

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

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

Atomic*系列原子类相关知识

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » Atomic*系列原子类相关知识
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏