Java并发编程专题系列之深入分析synchronized(基础篇)
synchronized同步关键字简介
synchronized是属于JVM层面的一个关键字,底层是通过一个monitor对象(管程对象)来完成,由于wait()/notify()等方法也依赖于monitor对象,所以只有在同步的块或者方法中才能调用wait/notify等方法
synchronized同步代码块底层实现
- synchronized同步语句块的实现使用monitorenter和 monitorexit 指令。
- monitorenter:指令指向同步代码块的开始位置
- monitorexit:指令则指明同步代码块的结束位置
synchronized获取锁
-
当执行monitorenter指令时,当前线程将试图获取 objectref(即对象锁) 所对应的 monitor的持有权,当 objectref的monitor 的进入计数器**为0,那线程可以成功取得 monitor,并将计数器值设置为 1,取锁成功。
-
如果当前线程已经拥有 objectref 的 monitor 的持有权,那它可以重入这个 monitor (关于重入性稍后会分析),重入时计数器的值也会加 1。
-
倘若其他线程已经拥有objectref 的 monitor 的所有权,那当前线程将被阻塞,直到正在执行线程执行完毕,即monitorexit指令被执行,执行线程将释放monitor(锁)并设置计数器值为0,其他线程将有机会持有 monitor ;**
为了保证在方法异常完成时 monitorenter 和 monitorexit 指令依然可以正确配对执行,编译器会自动产生一个异常处理器,这个异常处理器声明可处理所有的异常,它的目的就是用来执行 monitorexit 指令。
从字节码中也可以看出多了一个monitorexit指令,它就是异常结束时被执行的释放monitor的指令;
monitorenter(进入管程对象)
每个对象有一个管程对象(monitor),当monitor被占用时就会处于锁定状态;线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
如果monitor的进入计数器为0,则该线程进入monitor,然后将进入计数器设置为1,该线程即为monitor的所有者;
如果线程已经之前占用了该monitor,本次只是重新进入,则将monitor的进入计数器加1;
如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入计数器为0,再重新尝试获取monitor的所有权;
monitorexit(退出管程对象)
-
执行monitorexit的线程必须是objectref(即对象锁)所对应的monitor的所有者;
-
指令执行时,monitor的进入计数器减1,如果减1后进入计数器为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权.
同步方法中synchronized底层实现
方法级的同步是隐式,即无需通过字节码指令(monitorenter和monitorexit)来控制的。
![]()
它实现在方法调用和返回操作之中。
-
JVM可以从方法常量池中的方法表结构(method_info Structure) 中的ACC_SYNCHRONIZED访问标志区分一个方法是否同步方法。
-
当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有monitor(虚拟机规范中用的是管程一词)。
-
然后再执行方法,最后在方法完成(无论是正常完成还是非正常完成)时释放monitor。
在方法执行期间,执行线程持有了monitor,其他任何线程都无法再获得同一个monitor。如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那这个同步方法所持有的monitor将在异常抛到同步方法之外时自动释放。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
架构设计策略之风险驱动设计
风险驱动架构设计 风险驱动设计 风险 识别风险 描述风险 风险指导架构设计 技术选择 设定风险阈值 总结 你今日预咗风险未? 每次与项目成员沟通后,应该都会预感项目有风险吧。 大概都会遇到这些问题:进度风险、技术难点、需求变更、资源分配问题等等。 别和我说,基本没啥风险,项目很稳定。真有这样没风险的项目,那就不需要架构师了。毕竟这样的项目肯定会有成熟的“轮子”,直接借鉴就好了。 实际上,没风险的项目很少,需要开发的软件项目总有风险的,因为实际需求都是随时间变化的。 我们日常生活很多事情都是看风险来做决定的,最明显莫过于股票、基金等投资行为,在自己能接受的风险范围内进行决策。这是因为风险可以反映出真实世界的不确定性,而且是一个很好的决策指示器,它能帮助我们看清障碍,做出合理的选择。 因此,风险是可以指导我们进行优秀的架构设计,也就是说我们可以采用风险驱动模型进行架构设计。 风险驱动设计 风险驱动模型就是以风险为中心,根据合乎逻辑的理由进行决策权衡的模型。 采用风险驱动的话,必须要能回答以下这些问题: 项目的主要失败风险有哪些? 应对失败风险的技术有哪些? 何时结束和恢复架构设计? 为了解...
- 下一篇
Kubernetes概念篇:基本概念和术语
在开始使用之前,应当先了解一下关于Kubernetes的相关概念术语,对后续的学习、使用将有很大的帮助。(Kubernetes的概念比较多,建议加强理解,并清楚各种所处位置及关联!) Kubernetes中的大部分概念,如:Node、Pod、Replication Controller、Service等都可以看作是一种资源对象,几乎所有资源对象都可以通过Kubernetes提供的kubectl工具(或者API接口)执行增、删、改、查等操作并将其保存在etcd中持久化存储。 从这个角度来看,Kubernetes其实是一个高度自动化的资源控制系统,它通过跟踪对比etcd库里保存的“资源期望状态”与当前环境中的“实际资源状态”的差异来实现自动控制和自动纠错的高级功能。 本文将介绍Kubernetes中重要的资源对象,即:Kubernetes的基本概念和术语。 1、Master Master是指Kubernetes集群中的控制节点(Master Node),在每个Kubernetes集群里都需要有一个Master来负责整个集群的管理和控制,基本所有的控制命令都发给它,它负责具体的执行过程,后续...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8安装Docker,最新的服务器搭配容器使用
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Windows10,CentOS7,CentOS8安装Nodejs环境