最近看到一句话:内部锁synchronized不会造成锁泄漏(Lock Leak)。

锁泄漏是指一个线程获得某个锁以后,由于程序的错误、缺陷致使该锁一直没法被释放而导致其他线程一直无法获得该锁的现象。(摘自《Java多线程编程实战指南(核心篇)》--黄文海)

很好奇JVM是怎么保证的。

我想,Java代码,最终无非是编译成字节码,变成一条条指令,或许可以从指令入手研究一下。

1. 一个小例子

我们先来看看下面的代码。

 public class SynchronizedTest {

     private static final Object LOCK = new Object();

     public static void main(String[] args) {
synchronized (LOCK) {
foo();
}
} public static void foo() {
//do something...
}
}

很简单的一段代码,在临界区调用了一个方法。

通过javap -c SynchronizedTest.class ,得到如下信息,重点关注红框部分:

第5和第10行分别是monitorenter 和 monitorexit,这表示进入和退出临界区,临界区中间第6行调用了foo()这个方法。当退出临界区后,第11行直接goto第19行,即return,从当前方法返回,方法结束。

这是正常情况下的执行顺序。

那么如果在临界区中发生了异常(本例中是foo()可能发生异常),执行顺序又是怎么样的呢?

2. 异常表

在研究执行顺序之前,先学习一下异常表。

异常表实际上是Java代码的一部分,编译器使用异常表而不是简单的跳转命令来实现Java异常及finally处理机制。

上图的 Exception table即为异常表。它列举了哪些代码行的范围内,可能出现某种异常时,对应的处理机制。

那么异常表用在什么时候呢?

答案是异常发生的时候,当一个异常发生时

1.JVM会在当前出现异常的方法中,查找异常表,是否有合适的处理者来处理

2.如果当前方法异常表不为空,并且异常符合处理者的from和to节点,并且type也匹配,则JVM调用位于target的调用者来处理。

3.如果上一条未找到合理的处理者,则继续查找异常表中的剩余条目

4.如果当前方法的异常表无法处理,则向上查找(弹栈处理)刚刚调用该方法的调用处,并重复上面的操作。

5.如果所有的栈帧被弹出,仍然没有处理,则抛给当前的Thread,Thread则会终止。

6.如果当前Thread为最后一个非守护线程,且未处理异常,则会导致JVM终止运行。

以上就是JVM处理异常的一些机制。

】--以上摘自 详解JVM如何处理异常

具体到本例中

1. 当临界区发生异常,JVM查找异常表,发现符合第一行记录(异常发生点在6和11行(不包括第11行)之间,任意异常类型),于是跳到第14行,即第10行的monitorexit要么不执行,要么执行抛出异常,总之无法成功执行。

2. 从14行一路执行下去,到16行,再次monitorexit,此时释放锁。18行抛出上面获取到的异常,19行从当前方法返回void, 结束方法的运行。

3. 如果第2步过程中又发生异常,根据异常表第二行记录(异常点发生在14和17行(不包括第17行)之间,任意异常类型),会再次跳到14行,重新执行第2步,循环直到monitorexit指令成功执行。

这样就保证了monitorexit一定能够执行成功,锁一定会被释放。

简单分析synchronized不会锁泄漏的原因的更多相关文章

  1. java里的锁总结(synchronized隐式锁、Lock显式锁、volatile、CAS)

    一.介绍 首先, java 的锁分为两类: 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 jvm 层面实现,使用的时候看不见: 第二类是在 jdk5 后增加的 Lock ...

  2. (转)Synchronized(对象锁)和Static Synchronized(类锁)的区别

    场景:面试的时候经常用得到! 1 综述 Synchronized和Static Synchronized区别 一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全 ...

  3. 线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)

    接触过线程安全的同学想必都使用过synchronized这个关键字,在java同步代码快中,synchronized的使用方式无非有两个: 通过对一个对象进行加锁来实现同步,如下面代码. synchr ...

  4. Java多线程系列 基础篇06 synchronized(同步锁)

    转载 http://www.cnblogs.com/paddix/ 作者:liuxiaopeng http://www.infoq.com/cn/articles/java-se-16-synchro ...

  5. 关于Synchronized的偏向锁,轻量级锁,重量级锁,锁升级过程,自旋优化,你该了解这些

    前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized(如有不懂请移至传送门,关于Synchronized的偏向锁,轻量级锁,重量级锁,锁升级过程,自旋优 ...

  6. 精通java并发-synchronized关键字和锁

    目前CSDN,博客园,简书同步发表中,更多精彩欢迎访问我的gitee pages synchronized关键字和锁 示例代码 public class MyThreadTest2 { public ...

  7. 再有人说synchronized是重量级锁,就把这篇文章扔给他看

    synchronized作为Java程序员最常用同步工具,很多人却对它的用法和实现原理一知半解,以至于还有不少人认为synchronized是重量级锁,性能较差,尽量少用. 但不可否认的是synchr ...

  8. JAVA多线程之Synchronized关键字--对象锁的特点

    一,介绍 本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章 二,分析 s ...

  9. AbstractQueuedSynchronizer的简单分析

    说明:本作者是文章的原创作者,转载请注明出处:本文地址:http://www.cnblogs.com/qm-article/p/7955781.html 一.AbstractQueuedSynchro ...

随机推荐

  1. elasticsearch sql插件 2.4及以下版本配置

    github地址:https://github.com/NLPchina/elasticsearch-sql/ 方式一:github elasticsearch-sql上提供的安装方法cmd进入到本地 ...

  2. Intellij IDEA导入JAVA项目并启动(哈哈哈,天天都有人问)

    最近有很多同学,竟然不知道如何使用Intellij IDEA打开Java项目并启动 现在来讲一下,希望不要忘记了 1.打开IDEA开机页面 Maven项目 2.Maven项目是以pom文件引入各项ja ...

  3. PHP之Memcache和Memcached

    本篇文章向大家介绍的是PHP中的Memcache和Memcached ,有兴趣的朋友可以看一下 **Memcache介绍:**Memcache是一套分布式缓存系统,分布式就是说可以在多台服务器上同时安 ...

  4. Flutter移动电商实战 --(31)列表页_列表切换交互制作

    点击左侧的大类右边的小类也跟着变化 新建provide 要改变哪里就建哪里的provide,我们现在要改变的是右边的商品列表的数组. category_goods_list.dart 这样我们的pro ...

  5. 【Python】对我自己的博客进行统计,看看哪年哪月发帖量最大

    代码很简单,主要利用了requests进行网络访问,beautifulSoup进行页面文本分析,re进行正则表达式抽取文字,前面两个需要pip install name去安装,后者是内部对象所以不用安 ...

  6. based on Greenlets (via Eventlet and Gevent) fork 孙子worker 比较

    Design — Gunicorn 19.9.0 documentationhttp://docs.gunicorn.org/en/stable/design.html#async-workers e ...

  7. 花椒直播基于golang的中台技术实践

    https://github.com/gopherchina/conference/blob/master/2019/2.7%20花椒直播基于golang的中台技术实践%20-%20周洋.pdf 花椒 ...

  8. 重学C语言

    重学C语言 #include <stdio.h> int main() { ; ; printf("I am %d year old.\n",age); printf( ...

  9. 为什么使用 Web Services?

    最重要的事情是协同工作 由于所有主要的平台均可通过 Web 浏览器来访问 Web,不同的平台可以借此进行交互.为了让这些平台协同工作,Web 应用程序被开发了出来. Web 应用程序是运行在 Web ...

  10. 82. 删除排序链表中的重复元素 II

    # 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字,比如: # 输入: 1->2->3->3->4->4->5 # 输出: 1 ...