您现在的位置是:首页 > 编程 > 

深入理解synchronized实现原理

2025-07-26 14:31:22
深入理解synchronized实现原理 前言java中的锁大家很快就能想到synchronized和lock,那么synchronized实现原理是怎样呢?本文将深入讲解synchronized实现原理。简介synchronized关键字保证方法或者代码块在运行时,同一时刻只有一个方法可以进入临界区,同时它还可以保证共享变量的内存可见性。实现原理synchronized 可以作用于方法和代码快,

深入理解synchronized实现原理

前言

java中的锁大家很快就能想到synchronized和lock,那么synchronized实现原理是怎样呢?本文将深入讲解synchronized实现原理。

简介

synchronized关键字保证方法或者代码块在运行时,同一时刻只有一个方法可以进入临界区,同时它还可以保证共享变量的内存可见性。

实现原理

synchronized 可以作用于方法和代码快,具体如下图:

图片.png

作用于方法和代码块的实现原理是不同的,代码块采用的是monitorenter、monitorexit指令。而方法采用的是ACC_SYCHROIZED指令。

作用于代码块代码语言:javascript代码运行次数:0运行复制
csharp 代码解读复制代码  public synchronized void test1(){
     synchronized (this)
    {
          println("this is test method");
    }
  }
图片.png

说明:从编译后的源码可以得知,代码块的同步jvm的实现采用的是关键字monitorenter、monitorexit。每个对象都与一个monitor相关联。当且仅当拥有所有者时(被拥有),monitor才会被锁定。执行到monitorenter指令的线程,会尝试去获得对应的monitor。

加锁的实现

图片.png

说明:加锁采用是monitorenter指令,每个对象维护着一个记录着被锁次数的计数器, 对象未被锁定时,该计数器为0。线程进入monitor(执行monitorenter指令)时,会把计数器设置为1.当同一个线程再次获得该对象的锁的时候,计数器再次自增.当其他线程想获得该monitor的时候,就会阻塞,直到计数器为0才能成功。

释放锁的实现

图片.png

说明:释放锁采用的是monitorexi指令,线程执行monitorexit指令,就会让monitor的计数器减一。如果计数器为0,表明该线程不再拥有monitor。其他线程就允许尝试去获得该monitor。

作用于方法
图片.png

说明:当调用一个设置了ACC_SYCHROIZED标志的方法,执行线程需要先获得monitor锁,然后开始执行方法,方法执行之后再释放monitor锁,当方法不管是正常return还是抛出异常都会释放对应的monitor锁。实现的流程图如下:

图片.png

小结

不管是作用于方法还是同步块,其加锁的原理都是通过monitor来实现的,那么monitor如何实现呢?

Monitor实现原理

关于Java Monitor的工作机理如图所示:

图片.png
  • 获取monitor的线程,会进入_EntryList队列。
  • 当某个线程获取到对象的monitor后,进入_Owner区域,设置为当前线程,同时计数器_count加1。
  • 如果线程调用了wait()方法,则会进入_WaitSet队列。它会释放monitor锁,即将_owner赋值为null,_count自减1,进入_WaitSet队列阻塞等待。
  • 如果其他线程调用 notify() / notifyAll() ,会唤醒_WaitSet中的某个线程,该线程再次尝试获取monitor锁,成功即进入_Owner区域。
  • 同步方法执行完毕了,线程退出临界区,会将monitor的owner设为null,并释放监视锁。
小结

虽然monitor我们已经知道了相关的实现原理,但是monitor与对象又是如何进行关联呢?

对象与monitor关联

对象与monitor的关联其原理图如下:

图片.png
对象结构

在虚拟机中,对象在内存中存储的布局可以分为块区域:对象头、实例数据和对象填充。

图片.png
  • 实例数据:对象真正存储的有效信息,存放类的属性数据信息,包括父类的属性信息;
  • 对齐填充:由于虚拟机要求 对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐。
  • 对象头:Hotspot虚拟机的对象头主要包括两部分数据:Mark Word(标记字段)、Class Pointer(类型指针)。
对象头

而对象头又分为:Mark Word、类型指针、数组长度。

图片.png
  • Mark Word:主要用于存储自身运行时数据
  • 类型指针:指向方法区中该 class的对象,JVM 通过此字段来判断当前对象是哪个类的实例
  • 数组长度:当且仅当对象是数组时才会有该字段。

Mark Word

Mark Word 用于存储对象自身的运行时数据,包含哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等。

图片.png

说明:当锁其膨胀成重量级锁后,其他竞争的线程进来就不会自旋了,而是直接阻塞等待,并且 Mark Word 中的内容会变成一个监视器(monitor)对象,用来统一管理排队的线程。而monitor对象与每个对象都会关联。monitor对象本质上是一个同步机制,保证了同时只有一个线程能够进入临界区,在 HotSpot的虚拟机中,是由C++类ObjectMonitor实现的。

总结

本文对于synchronized的原理进行详细的讲解,关于synchronized锁的升级将在后续的文章进行讲解。如有疑问请随时反馈。

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1222279.html

相关标签:无
上传时间: 2025-07-25 18:27:11
留言与评论(共有 15 条评论)
本站网友 海豹油的作用
7分钟前 发表
当某个线程获取到对象的monitor后
本站网友 黑木耳的营养价值
3分钟前 发表
锁状态标志
本站网友 大理二手房
1分钟前 发表
并且 Mark Word 中的内容会变成一个监视器(monitor)对象
本站网友 监控系统下载
24分钟前 发表
当且仅当拥有所有者时(被拥有)
本站网友 陈小明
3分钟前 发表
如有疑问请随时反馈
本站网友 九江二手房
29分钟前 发表
线程退出临界区
本站网友 杭州美食攻略
6分钟前 发表
同时它还可以保证共享变量的内存可见性
本站网友 抗菌素分类
30分钟前 发表
每个对象维护着一个记录着被锁次数的计数器
本站网友 朝阳医院网上预约挂号
16分钟前 发表
其他竞争的线程进来就不会自旋了
本站网友 尼曼中国
19分钟前 发表
如果计数器为0
本站网友 胰腺癌晚期症状
20分钟前 发表
当某个线程获取到对象的monitor后
本站网友 上海市二手房
6分钟前 发表
成功即进入_Owner区域
本站网友 普陀区妇幼保健院
20分钟前 发表
当且仅当拥有所有者时(被拥有)
本站网友 4399tnt
3分钟前 发表
线程退出临界区