线程基础知识06 synchronized---使用javap查看相关指令
1 示例-简单同步代码块
public class SychTest9 {
public static void main(String[] args) {
Object o = new Object();
synchronized (o){
System.out.println("aaa");
}
}
}
使用javap查看指令(复制了部分)
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: new #2 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: astore_1
8: aload_1
9: dup
10: astore_2
11: monitorenter
12: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
15: ldc #4 // String aaa
17: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
20: aload_2
21: monitorexit
22: goto 30
25: astore_3
26: aload_2
27: monitorexit
28: aload_3
29: athrow
30: return
可以看到下面三个指令,一个monitorenter 指令,两个monitorexit
11: monitorenter 进入管程 21: monitorexit 出管程 27: monitorexit 出管程
synchronized 同步语句块的实现使用的是 monitorenter 和 monitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置, monitorexit 指令则指明同步代码块的结束位置。**
当执行 monitorenter 指令时,线程试图获取锁也就是获取 对象监视器 monitor 的持有权
在 Java 虚拟机(HotSpot)中,Monitor 是基于 C++实现的,由ObjectMonitor实现的。每个对象中都内置了一个 ObjectMonitor对象。
另外,wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。
在执行monitorenter时,会尝试获取对象的锁,如果锁的计数器为 0 则表示锁可以被获取,获取后将锁计数器设为 1 也就是加 1。
在执行 monitorexit 指令后,将锁计数器设为 0,表明锁被释放。如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止
这里为什么有两个monitorexit指令呢?
第一个monitorexit指令是同步代码块正常释放锁的一个标志;
如果同步代码块中出现Exception或者Error,则会调用第二个monitorexit指令来保证释放锁
2 示例-简单同步代码块+异常
在同步代码块中手动抛出异常
public class SychTest10 {
public static void main(String[] args) throws Exception {
Object o = new Object();
synchronized (o){
System.out.println("aaa");
throw new Exception();
}
}
}
使用javap查看指令(复制了部分)
/*
public static void main(java.lang.String[]) throws java.lang.Exception;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: new #2 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: astore_1
8: aload_1
9: dup
10: astore_2
11: monitorenter
12: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
15: ldc #4 // String aaa
17: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
20: new #6 // class java/lang/Exception
23: dup
24: invokespecial #7 // Method java/lang/Exception."<init>":()V
27: athrow
28: astore_3
29: aload_2
30: monitorexit
31: aload_3
32: athrow
*/
可以看到monitorenter和monitorexit,athrow和athrow,保证释放锁
11: monitorenter 27: athrow 30: monitorexit 32: athrow
3 示例-普通同步方法
public class SychTest11 {
public synchronized void aa() {
System.out.println("aaa");
}
public static void main(String[] args) {
}
使用javap查看指令(复制了部分)
public synchronized void aa();
descriptor: ()V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String aaa
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
可以看到,可以没有了monitorenter和monitorexit指令,但是有一个标识ACC_SYNCHRONIZED,标识它是一个同步方法
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
4 示例 静态同步方法
public class SychTest12 {
public static synchronized void aa() {
System.out.println("aaa");
}
public static void main(String[] args) {
aa();
}
}
使用javap查看指令(复制了部分)
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=0, args_size=0
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String aaa
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 6: 0
line 7: 8
可以看到,可以没有了monitorenter和monitorexit指令,但是有一个标识ACC_SYNCHRONIZED,标识它是一个同步方法,且ACC_STATIC标识是静态方法
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
5 小结
synchronized 同步语句块的实现使用的是 monitorenter 和 monitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。正常情况下回有两个monitorexit指令,为了在出现异常也能够成功释放锁。
synchronized 修饰的方法并没有 monitorenter 指令和 monitorexit 指令,取得代之的确实是 ACC_SYNCHRONIZED 标识,该标识指明了该方法是一个同步方法。
不过两者的本质都是对监视器 monitor 的获取
线程基础知识06 synchronized---使用javap查看相关指令的更多相关文章
- Java并发编程(一):线程基础知识以及synchronized关键字
1.线程与多线程的概念:在一个程序中,能够独立运行的程序片段叫作“线程”(Thread).多线程(multithreading)是指从软件或者硬件上实现多个线程并发执行的技术. 2.多线程的意义:多线 ...
- java线程基础知识----线程与锁
我们上一章已经谈到java线程的基础知识,我们学习了Thread的基础知识,今天我们开始学习java线程和锁. 1. 首先我们应该了解一下Object类的一些性质以其方法,首先我们知道Object类的 ...
- java线程基础知识----线程基础知识
不知道从什么时候开始,学习知识变成了一个短期记忆的过程,总是容易忘记自己当初学懂的知识(fuck!),不知道是自己没有经常使用还是当初理解的不够深入.今天准备再对java的线程进行一下系统的学习,希望 ...
- Windows核心编程 第六章 线程基础知识 (上)
第6章 线程的基础知识 理解线程是非常关键的,因为每个进程至少需要一个线程.本章将更加详细地介绍线程的知识.尤其是要讲述进程与线程之间存在多大的差别,它们各自具有什么作用.还要介绍系统如何使用线程内核 ...
- Java__线程---基础知识全面实战---坦克大战系列为例
今天想将自己去年自己编写的坦克大战的代码与大家分享一下,主要面向学习过java但对java运用并不是很熟悉的同学,该编程代码基本上涉及了java基础知识的各个方面,大家可以通过练习该程序对自己的jav ...
- Java 线程基础知识
前言 什么是线程?线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元.一个标准的线程由线程 ID,当前指令指针 (PC),寄存器集合和堆栈组成.另外,线 ...
- Windows核心编程 第六章 线程基础知识 (下)
6.6 线程的一些性质 到现在为止,讲述了如何实现线程函数和如何让系统创建线程以便执行该函数.本节将要介绍系统如何使这些操作获得成功. 图6 - 1显示了系统在创建线程和对线程进行初始化时必须做些什么 ...
- 基础知识系列☞Abstract和Virtual→及相关知识
转载地址→http://www.cnblogs.com/blsong/archive/2010/08/12/1798064.html 在C#的学习中,容易混淆virtual方法和abstract方法的 ...
- Java多线程系列 基础篇06 synchronized(同步锁)
转载 http://www.cnblogs.com/paddix/ 作者:liuxiaopeng http://www.infoq.com/cn/articles/java-se-16-synchro ...
- Java并发之线程管理(线程基础知识)
因为书中涵盖的知识点比较全,所以就以书中的目录来学习和记录.当然,学习书中知识的时候自己的思考和实践是最重要的.说到线程,脑子里大概知道是个什么东西,但很多东西都还是懵懵懂懂,这是最可怕的.所以想着细 ...
随机推荐
- c++ const和指针
const int *p: 定义指针,指向的变量的值不能修改(指向整型常量或普通整型,但值不能通过指针修改) int const *p: 同上 int * const p=&a: 一直指向a, ...
- kettle 链接oracle12c
jdbc连接cdb数据库时,url兼容以下2种模式: "jdbc:oracle:thin:@192.168.75.131:1521:oracle12c" "jdbc:or ...
- 网络I/O模型 解读
网络.内核 网卡能「接收所有在网络上传输的信号」,但正常情况下只接受发送到该电脑的帧和广播帧,将其余的帧丢弃. 所以网络 I/O 其实是网络与服务端(电脑内存)之间的输入与输出 内核 查看内核版本 : ...
- 【大数据面试】【框架】Shuffle优化、内存参数配置、Yarn工作机制、调度器使用
三.MapReduce 1.Shuffle及其优化☆ Shuffle是Map方法之后,Reduce方法之前,混洗的过程 Map-->getPartition(标记数据的分区)-->对应的环 ...
- day33-JSON&Ajax01
JSON&Ajax01 JSON 在线文档 AJAX 在线文档 1.JSON介绍 JSON指的是JavaScript对象表示法( JavaScript Object Notation),JSO ...
- live-player live-pusher惨案
昨天遇到的问题,旧项目: 一个页面同时使用live-player和live-pusher时候遇到的问题,live-pusher正常,live-player无效,没有任何报错 打log 所有livepl ...
- day36-ThreadLocal
ThreadLocal 线程数据共享和安全 1.什么是ThreadLocal? ThreadLocal的作用,可以实现在同一个线程数据共享,从而解决多线程数据安全问题 当http请求发送到Tomcat ...
- 事件 jQuery类库、Bootstrap页面框架
目录 jQuery查找标签 基本选择器 组合选择器 层级选择器 属性选择器 基本筛选器 表单筛选器 筛选器方法 链式的本质(jQuery一行代码走天下) 操作标签 class操作 位置操作 文本操作 ...
- 命令指定IP端口号
tcping命令是针对tcp监控的,也可以看到ping值,即使源地址禁ping也可以通过tcping来监控服务器网络状态,除了简单的ping之外,tcping最大的一个特点就是可以指定端口. 将下载好 ...
- 使用命令行运行用例时提示python.exe: Error while finding module specification for 'testcase_1.Test'.....
文件路径 输入命令 D:\demo>python -m unittest unittest_1/testcase_1.Test结果提示 ModuleNotFoundError: No modul ...