美文网首页
五、synchronized

五、synchronized

作者: 此间有道 | 来源:发表于2020-08-16 00:15 被阅读0次

    多线程访问相同的共享可变的变量时,通常需要使用加锁的方式实现同步,避免竞态条件发生。同步的其中一个特征就是互斥,通过使访问顺序串行化,使得并发结果合法和可预期。synchronized是java的关键字,其通过java的内置锁机制实现多线程同步。

    一、synchronized的三种锁形态

    synchronized在jdk1.5前只有重量级锁,开销较大。为了应对低竞争的场景在jdk1.5增加了偏向锁和轻量级锁。对象的锁状态通过对象头里的markword标识。


    mark word
    1. 偏向锁
    image.png

    1)场景:在一个时刻只有一个线程请求锁,没有竞争;
    2)关键参数:
    -XX:+UseBiasedLocking # 是否开启偏向锁,jdk1.6以后默认开启
    -XX:BiasedLockingStartupDelay=4000 # 偏向锁延迟启动时间,
    -XX:BiasedLockingDecayTime=25000 # 重置撤销次数的时间阈值
    -XX:BiasedLockingBulkRevokeThreshold=40 # 偏向锁批量撤销阈值
    -XX:BiasedLockingBulkRebiasThreshold=20 # 偏向锁批量重偏向阈值

    Note:

    • 查看jvm各参数默认值
      java -XX:+PrintFlagsInitial
    • 查看jvm运行参数值(其中被赋值号为:=的值是被修改过,与初始值不同)
      java -XX:+PrintFlagsFinal
    • 查看jvm运行时的参数的命令
      jinfo -flags <pid>
      jinfo -flag <name> <pid>

    3)实现原理:markword标识出偏向锁状态,且保存当前持有锁的线程ID。然后在其线程栈上隐式保存递归次数。


    image.png

    4)优点:在无竞争的情况下开销较小,包括cpu(无须切换上下文和线程调度)和内存(无须分配管程对象)开销。
    5)缺点:锁撤销开销较大,需要挂起锁定线程,遍历其线程栈,修改锁记录。甚至比轻量级锁和重量级锁的开销还大。目前HotSpot使用安全点的STW和启发式撤销方法,减少撤销次数,提高性能。
    6)可重偏向的条件

    • 线程ID为空
    • epoch无效

    Note1: 当类元数据中的epoch与类对象的对象头中的epoch值相等时,表示当前偏向锁有效;否则该偏向锁失效,可重偏向;通过引入epoch减小了重偏向的开销;


    image.png

    Note2:在调用hashcode时会撤销偏向锁来还原hashcode的占位;
    Note3: 调用wait,notify会膨胀为重量级锁。触发管程对象分配和初始化;

    2. 轻量级锁(也称为thin lock)
    image.png

    1)场景:在一段时间内请求的锁的线程较少,且持有锁的线程执行时间短,持有锁的时间短,其他等待线程在有限的自旋等待期可以得到锁。
    2)实现结构——栈上锁记录

    锁记录在堆栈上分配,在解释执行期间显式分配,或在编译时隐式分配。锁定记录包含一个可以放置移位标记字的位置,以及一个指向被锁定对象的指针。对象指针在分配时由解释器或编译器初始化,当锁被薄锁或胖锁时,移位的标记字被初始化。
    from: www.diva-portal.org/smash/get/diva2:754541/FULLTEXT01.pdf

    栈上锁记录

    3)锁升级过程

    当一个线程试图获取一个已经被其他线程持有的轻量级锁(CAS失败)时,非所有者线程将尝试对该锁进行膨胀。在锁膨胀期间,为对象分配和初始化重量级对象监视器结构。膨胀线程将尝试在循环中对锁进行升级,直到成功,或直到其他线程成功地升级锁为止。
    from: www.diva-portal.org/smash/get/diva2:754541/FULLTEXT01.pdf

    Note1: 调用wait,notify会膨胀为重量级锁。触发管程对象分配和初始化;

    3. 重量级锁(也称为fat lock)
    image.png

    1)管程对象——monitor
    通过对象关联的管程对象实现线程阻塞,唤醒机制。其主要依赖操作系统级的互斥量来实现。
    2)WaitSet,EntrySet


    image.png
    • 准备争抢会进入临界区的线程会进入EntrySet;
    • 只有一个线程会进去临界区,独占锁;
    • 获取锁的线程执行wait方法会让出锁,并进去WaitSet;
    • WaitSet中的线程需要被唤醒才能进入EntrySet,然后再参与竞争;

    3)优点:
    在多线程并发激烈的情况下性能表现好,让未获得锁的线程让出时间片和cpu使用权,减少资源消耗。

    四、与juc包ReentrantLock对比

    ReentrantLock优点:

    • 公平锁和非公平锁
    • 阻塞和非阻塞
    • 超时机制
    • 读写锁
    • 多个条件队列

    参考

    1. Java 的偏向锁是怎么实现的? - RednaxelaFX的回答 - 知乎
    2. Evaluating and improving biased locking in the HotSpot virtual machine
    3. https://www.cnblogs.com/LemonFive/p/11248248.html
    4. https://zhuanlan.zhihu.com/p/127884116

    相关文章

      网友评论

          本文标题:五、synchronized

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