深入理解共享模型之无锁

5.共享模型之无锁

  1. 获取共享变量时,为了保证该变量的可见性,需要使用volatile修饰
    CAS必须借助volatile才能读取到共享变量的最新值来实现比较并交换的效果

  2. 为什么无锁效率高? 无锁情况下,即使重试失败,线程始终在高速运行,没有停歇。而synchronized会让线程在没有获得锁的时候,发生上下文切换,进入阻塞。
    但无锁情况下,因为线程要保持运行,需要额外cpu的支持,如果没有,虽然不会进入阻塞,但由于没有分到时间片,仍然会进入可运行状态,还是会导致上下文切换。

  3. CAS的特点:结合CAS和volatile可以实现无锁并发,适用于线程数少,多核cpu的场景下
    CAS是基于乐观锁的思想,不怕别的线程来修改共享变量,就算改了也没关系,重试就可以
    synchronized是基于悲观锁的思想,得防着其他线程来修改共享变量。
    CAS体现的是无锁并发、无阻塞并发。 因为没有使用synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一 但如果竞争激励,重试必然频繁发生,反而效率会受到影响。

  4. 原子整数:JUC并发包提供了AtomicBoolean,AtomicInterger,AtomicLong

  5. 原子引用: AtomicReference,AtomicMarkableReference,AtomicStampedReference
    主线程仅能判断出共享变量的值与最初值A是否相同,不能感知到这种从A改为B又改为A的情况,如果主线程希望只要有其他线程改变过了共享变量(即ABA问题),那么自己的cas就算失败。需要加个版本号解决。
    通过AtomicStampedReference可以给原子引用加上版本号,追踪原子引用整个的变化过程。可以知道,引用变量中途更改了几次。 PS:但是有时候,并不关心引用变量更改了几次,只是单纯地关心是否更改过,所以就有了AtomicMarkableReference

  6. 函数式接口:suppier 提供者()-> 结果 | function 参数- >结果 Bifunction 2个参数->结果
    consume 参数->()

  7. 字段更新器:AtomicReferenceFieldUpdater,AtomicIntegerFieldUpdater,AtomicLongFieldUpdater
    利用字段更新器,可以针对对象的某个Field进行原子操作,只能配合volatile修饰的字段使用,否则会出现异常

  8. 原子累加器LongAdder: 跟Atomic相比可以大幅提高性能,因为它在有竞争时,设置多个累加单元,线程1累加Cell[0],线程2累加Cell[1],最后将结果汇总。这样他们在累加时操作不同Cell变量减少了CAS重试失败,提高性能
    LongAdder类中的几个关键域
    transient volatile Cell[] cells; 累加单元数组,懒惰初始化
    transient volatile long base; 基础值,如果没有竞争,则用cas累加这个域
    transient volatile int cellsBusy; 在cells创建或扩容时,置为1,表示加锁
    transient表示不被序列化
    @sun.misc.Contended(竞争) 该注解为防止缓存行伪共享
    因为cpu与内存的速度差异很大,需要靠预读数据至缓存来提升效率
    而内存中的缓存以缓存行为单位,每个缓存行对应着一块内存,一般是64byte(8个long)
    缓存的加入会造成数据副本的产生,即同一份数据会缓存在不同核心的缓存行中
    cpu要保证数据的一致性,如果某个cpu核心更改了数据,其他cpu核心对应的整个缓存行必须失效
    9.Unsafe

  9. Unsafe对象提供了非常底层的,操作内存、线程的方法,Unsafe对象不能直接调用,只能通过反射获得,通过偏移量的方式来定位需要操作的对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值