并发编程艺术-2

作者: e86dab508bc1 | 来源:发表于2018-04-14 10:26 被阅读0次

    本篇文章主要介绍并发的底层实现原理:volatile , synchronized, 原子操作。

    1. volatile:
      保证了所有的线程看到的变量的值是一样的,为了更好的理解volatile,这边插播一些相关背景知识:大家都知道CPU 和 内存之间的速度是不在同一个层次上面的,CPU 速度远远超过了内存的速度,为了平衡两者,在两者中间加入了高速缓存,常见的有L1,L2,L3,其中L1对于CPU 的处理速度影响最大,依次递减,这样就导致,CPU 和 内存之间的数据有时候需要经过中间高速缓存区域,这边转变volatile 变量操作成 汇编语言,可以发现里面出现了lock 前缀的指令, 它的作用是 将当前处理器中缓存的该变量修改值写回到内存中,这时其他处理器的嗅探器检测到在系统总线上面发生的数据改变,发现对应的缓存行(CPU 高速缓存区用来保存缓存值得区域,根据系统大小进行设定每一个缓存行的大小,有时候为了提高并发性,可以填充相应的缓存行) 对应的内存地址被修改,这样CPU就会将当前该值所在的缓存行设置成无效状态,这样下面访问的时候,由于缓存行失效了,需要从内存中重新读取。

    2.synchronized:
    用处: 底层语义通过生成 monitorenter 和 monitorexit 指令来进行同步,其实每一个对象都有一个监视器锁(monitor),wait/notify 也倚赖monitor,因此在只有在同步块中才能调用wait/notify.

    • Thrown to indicate that a thread has attempted to wait on an
    • object's monitor or to notify other threads waiting on an object's
    • monitor without owning the specified monitor.

    monitor : 本质是依赖于底层操作系统的互斥锁,所以就会变成用户态切换到核心态,这个成本很高,所以这就是synchronized 效率低的原因。

    如果monitor 进入数为0,线程进入monitor,然后将进入数设置为1,则该进程就是monitor 所有者,该线程占有monitor,重新进入的时候,monitor进入数加一, 通过JAVA 对象头部里面的锁标志位进行操作,java 对象头部锁的状态有无锁,偏向锁,轻量锁,重量级锁, 锁的力度依次递增,只能升级,不能降级,

    (1) 偏向锁: 大部分情况下面,一个线程可以总是获得到同一个对象,为了减少锁的代价,引入偏向锁,根据记录线程的ID,下次该线程又进入的时候就可以不要加锁和解锁了,但是前提是需要测试是否指向该线程,如果检测成功,说明该线程已经获得了锁,失败的话,那就要检查Mark Word 里面的偏向锁标志是否为1,是的话,将偏向锁指向该线程,否则使用CAS竞争锁。

    CAS : compare and set
    在硬件层面上面提供原子性操作,使用指令cmpXchg, 会出现 ABA 问题, 可以通过AtomicStampedReference 中使用的Pair-> [reference,integer]来解决。

    (2)轻量级锁:JVM 在当前栈帧中创建了存储锁记录的空间,将当前对象的Mark Word 复制到锁记录下面,然后通过CAS 来竞争锁,成功,获得锁,失败,就自旋。在解锁时,使用CAS 替换回原来的Mark Word,成功表示没有竞争,否则膨胀为重量级锁,其他想获得锁的线程都将被阻塞。

    用法:
    包括一般是用在普通同步方法(锁的是当前实例对象),同步块(synchronized 括号里面的对象),静态同步方法(类的class 对象),

    偏向锁,轻量级锁,重量级锁的比较.png

    3.原子操作:
    原子本意 :不可分割的最小粒子,那原子操作就可以引申为不可分割的操作,相当于没有中间商赚差价,看不到中间的状态。

    处理器如何实现原子操作 :
    处理器先保证基本的内存操作是原子性,多处理时只有一个处理器访问,提供以下两种机制保证复杂内存原子操作

    (1)使用总线锁:处理器发出了lock#信号,其他处理器的请求被阻塞了,独占共享内存
    (2)使用缓存锁:总线锁会使得其他处理器不能使用系统总线,导致性能下降,缓存存在处理器的L1,L2,L3,则原子性可以直接在处理器内部实现,锁定缓存行之后操作完成之后回写内存,允许了缓存一致性机制导致其他处理器回写的缓存行无效。

    JAVA 如何实现原子操作:
    (1) 循环CAS自旋(优缺点)
    (2)使用锁机制

    相关文章

      网友评论

        本文标题:并发编程艺术-2

        本文链接:https://www.haomeiwen.com/subject/xrhkkftx.html