您当前的位置: 首页 >  Java

小志的博客

暂无认证

  • 0浏览

    0关注

    1217博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java并发多线程编程——Synchronized关键字之偏向锁、轻量级锁及重量级锁

小志的博客 发布时间:2021-04-16 08:41:41 ,浏览量:0

部分参考: 《Java并发编程实战》 https://blog.csdn.net/lengxiao1993/article/details/81568130 https://blog.csdn.net/weixin_42213903/article/details/97044043 https://www.cnblogs.com/deltadeblog/p/9559035.html

目录
    • 一、synchronized 关键字之(偏向锁->轻量级锁->重量级锁)
    • 二、锁信息存在对象哪个地方
    • 三、对象头中的信息有哪些
    • 四、偏向锁(Biased Lock )的理解
    • 五、偏向锁、轻量级锁及重量级锁
    • 六、无锁 VS 偏向锁 VS 轻量级锁 VS 重量级锁

一、synchronized 关键字之(偏向锁->轻量级锁->重量级锁)

1、synchronized 代码块是由一对 monitorenter/moniterexit 字节码指令实现, monitor 是其同步实现的基础, Java SE1.6 为了改善性能, 使得 JVM 会根据竞争情况, 使用如下 3 种不同的锁机制

  • 偏向锁(Biased Lock )
  • 轻量级锁( Lightweight Lock)
  • 重量级锁(Heavyweight Lock)

上述这三种机制的切换是根据竞争激烈程度进行的, 在几乎无竞争的条件下, 会使用偏向锁, 在轻度竞争的条件下, 会由偏向锁升级为轻量级锁, 在重度竞争的情况下, 会升级到重量级锁。

二、锁信息存在对象哪个地方
  • 任何对象都可以作为锁,锁信息存在对象头中。
三、对象头中的信息有哪些
  • 非数组类型的对象头包括Mark Word 、Class Metadata Address
  • 数组类型的对象头包括Mark Word 、Class Metadata Address和Array Length三个部分 在这里插入图片描述
四、偏向锁(Biased Lock )的理解

1、偏向锁是什么

  • 锁不仅不存在多线程竞争,而且总是由同一个线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。JDK1.6之后 偏向锁默认开启。
  • 偏向锁是锁状态中最乐观的一种锁:从始至终只有一个线程请求同一把锁。

2、偏向锁对象头的Mark Word

线程IDEpoch对象分代年龄偏向锁的标志 是否偏向锁 0否 1是锁标志位线程ID(初始为00…代表未偏向Epoch对象分代年龄101

3、偏向锁优点

  • 只需要执行一次CAS即可获取锁
  • 采用延迟释放锁策略
  • 锁重入时,只需要判断mark_word.threadId(关于对象头的文章)是否为当前threadId即可

4、偏向锁缺点

  • 总体上只针对第一个线程有效,新线程获取锁时,会导致锁膨胀
  • 锁膨胀时,会导致stop the world (STW)
  • 与原生hashcode()互斥,导致偏向锁并非适应于所有的instance

5、偏向锁如何获取

  • JVM偏向锁默认已开启
  • 注意 :JVM 提供了关闭偏向锁的机制, JVM 启动命令指定如下参数即可
  • -XX:-UseBiasedLocking

6、偏向锁如何撤销

  • 偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁。
五、偏向锁、轻量级锁及重量级锁
  • 偏向所锁,轻量级锁都是乐观锁,重量级锁是悲观锁。
  • 一个对象刚开始实例化的时候,没有任何线程来访问它的时候。它是可偏向的,意味着,它现在认为只可能有一个线程来访问它,所以当第一个线程来访问它的时候,它会偏向这个线程,此时,对象持有偏向锁。偏向第一个线程,这个线程在修改对象头成为偏向锁的时候使用CAS操作,并将对象头中的ThreadID改成自己的ID,之后再次访问这个对象时,只需要对比ID,不需要再使用CAS在进行操作。
  • 一旦有第二个线程访问这个对象,因为偏向锁不会主动释放,所以第二个线程可以看到对象时偏向状态,这时表明在这个对象上已经存在竞争了,检查原来持有该对象锁的线程是否依然存活,如果挂了,则可以将对象变为无锁状态,然后重新偏向新的线程,如果原来的线程依然存活,则马上执行那个线程的操作栈,检查该对象的使用情况,如果仍然需要持有偏向锁,则偏向锁升级为轻量级锁,(偏向锁就是这个时候升级为轻量级锁的)。如果不存在使用了,则可以将对象回复成无锁状态,然后重新偏向。
  • 轻量级锁认为竞争存在,但是竞争的程度很轻,一般两个线程对于同一个锁的操作都会错开,或者说稍微等待一下(自旋),另一个线程就会释放锁。 但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁膨胀为重量级锁,重量级锁使除了拥有锁的线程以外的线程都阻塞,防止CPU空转。
六、无锁 VS 偏向锁 VS 轻量级锁 VS 重量级锁
  • 这四种锁是指锁的状态,专门针对synchronized的。
  • 偏向锁通过对比Mark Word解决加锁问题,避免执行CAS操作。
  • 轻量级锁是通过用CAS操作和自旋来解决加锁问题,避免线程阻塞和唤醒而影响性能。
  • 重量级锁是将除了拥有锁的线程以外的线程都阻塞。 在这里插入图片描述
关注
打赏
1661269038
查看更多评论
立即登录/注册

微信扫码登录

0.1513s