Java synchronized重量级锁实现过程浅析

作者:每天都要进步一点点 时间:2023-10-25 14:10:17 

一、什么是重量级锁

当有大量的线程都在竞争同一把锁的时候,这个时候加的锁,就是重量级锁。

Java synchronized重量级锁实现过程浅析

Java synchronized重量级锁实现过程浅析

这个重量级锁其实指的就是JVM内部的ObjectMonitor监视器对象:

ObjectMonitor() {
   _header       = NULL;//锁对象的原始对象头
   _count        = 0;//抢占当前锁的线程数量
   _waiters      = 0,//调用wait方法后等待的线程数量
   _recursions   = 0;//记录锁重入次数
   _object       = NULL;
   _owner        = NULL;//指向持有ObjectMonitor的线程
   _WaitSet      = NULL;//处于wait状态的线程队列,等待被唤醒
   _WaitSetLock  = 0 ;
   _Responsible  = NULL ;
   _succ         = NULL ;
   _cxq          = NULL ;
   FreeNext      = NULL ;
   _EntryList    = NULL ;//等待锁的线程队列
   _SpinFreq     = 0 ;
   _SpinClock    = 0 ;
   OwnerIsThread = 0 ;
   _previous_owner_tid = 0;
 }

二、重量级锁的演示

public class HightweightLockDemo02 {
   public static void main(String[] args) {
       Object objLock = new Object();
       new Thread(() -> {
           synchronized (objLock) {
               System.out.println(ClassLayout.parseInstance(objLock).toPrintable());
           }
       }, "t1").start();
       new Thread(() -> {
           synchronized (objLock) {
               System.out.println(ClassLayout.parseInstance(objLock).toPrintable());
           }
       }, "t2").start();
   }
}

运行程序:

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           1a 33 c9 e1 (00011010 00110011 11001001 11100001) (-506907878)
      4     4        (object header)                           43 01 00 00 (01000011 00000001 00000000 00000000) (323)
      8     4        (object header)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           1a 33 c9 e1 (00011010 00110011 11001001 11100001) (-506907878)
      4     4        (object header)                           43 01 00 00 (01000011 00000001 00000000 00000000) (323)
      8     4        (object header)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

可见,当多个线程共同抢占同一把锁的时候,锁对象MarkWord的最后三位是“010”,代表的就是一个重量级锁。

三、重量级锁的原理

以上述代码为例,synchronized获取的锁是重量级锁,synchronized修饰代码块,使用javap -p -v .\HightweightLockDemo02.class指令查看其字节码:

Java synchronized重量级锁实现过程浅析

在编译的时候,JVM会在同步块开始位置插入monitorenter指令,在同步块结束位置插入monitorexit指令。当线程执行到monitorenter指令时,会尝试获取对象所对应的Monitor所有权,如果获取成功,则表示获取到了锁,会在Monitor的_owner中存在当前线程的ID,这样它将处于锁定状态,除非退出同步块,否则其他线程无法获取得到这个Monitor。

Java synchronized重量级锁实现过程浅析

四、锁的优缺点对比

下表是对各种状态的锁的对比:

锁的类型优点缺点适用场景
偏向锁加锁和解锁不需要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距如果线程间存在锁竞争,会带来额外的锁撤销的消耗适用于只有一个线程访问同步块场景
轻量级锁竞争的线程不会阻塞,提高了程序的响应速度如果始终得不到锁竞争的线程,使用自旋会消耗CPU,导致CPU空转追求响应时间 同步块执行速度非常快
重量级锁线程竞争不使用自旋,不会消耗CPU线程阻塞,响应时间缓慢追求吞吐量 同步块执行时间较长

来源:https://weishihuai.blog.csdn.net/article/details/126536742

标签:Java,synchronized,重量级锁
0
投稿

猜你喜欢

  • Android RetainFragment状态保存的方法

    2023-06-03 03:35:08
  • Java针对封装数组的简单复杂度分析方法

    2022-12-22 03:28:58
  • java实现清理DNS Cache的方法

    2022-07-27 23:11:50
  • 微服务架构设计RocketMQ基础及环境整合

    2023-02-18 17:18:15
  • Java接口RandomAccess全面了解

    2023-09-11 19:05:29
  • Qt基础开发之Qt文件操作类QFile读写文件的详细方法与实例及QDataStream的使用方法

    2023-06-05 00:06:46
  • 详解Mybatis-plus中更新date类型数据遇到的坑

    2022-08-17 21:43:14
  • Winform控件Picture实现图片拖拽显示效果

    2022-04-01 05:49:54
  • C# 键盘Enter键取代Tab键实现代码

    2022-11-21 08:53:14
  • IDEA高效使用设置指南

    2023-10-30 01:39:37
  • SpringBoot+SpringSession+Redis实现session共享及唯一登录示例

    2023-10-07 07:56:17
  • Flutter SizedBox布局组件Widget使用示例详解

    2022-02-08 18:19:44
  • Java中关键字synchronized的使用方法详解

    2022-04-14 06:18:54
  • 浅析Android App的相对布局RelativeLayout

    2023-04-08 18:28:48
  • Android 7.0以上版本实现应用内语言切换的方法

    2022-12-21 00:25:31
  • Android自定义可循环的滚动选择器CycleWheelView

    2023-04-06 00:43:16
  • .NET(C#):Emit创建异常处理的方法

    2023-11-05 04:03:02
  • Android图片加载库Glide用法

    2023-08-11 10:12:01
  • 基于Java实现多线程下载并允许断点续传

    2021-07-19 03:05:52
  • java语言图形用户登录界面代码

    2021-09-11 23:19:34
  • asp之家 软件编程 m.aspxhome.com