119-结合jconsole,jstack以及汇编指令认识synchronized关键字
上一节使用的synchronized到底是什么呢?
例子:在动物园检票的时候(前提:只有一台检票机,游客没有排队),每次只能有一位游客通过检票机进入动物园。游客类比多个线程,检票机类比synchronized。此时synchronized内部为单线程,串行化运行程序代码
目的:让synchronized代码块里边的代码串行化运行,让共享数据串行被操作。
代码:
public class SynchronizedTest {
// 代码规范:final命名的变量需要使用大写
private static final Object LOCK = new Object();
public static void main(String[] args) {
// 任务
Runnable runnable = () -> {
synchronized (LOCK) {
Thread.sleep(500_000);
}
};
// 创建并启动线程
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
Thread t3 = new Thread(runnable);
t1.start();t2.start();t3.start();
}
}
jconsole工具
在终端输入命令:
jconsole
。打开Java监视和管理控制台,并选择名为SynchronizedTest的本地进程点击线程,查看Thread0、Thread1、Thread2
Thread-0:状态: TIMED_WAITING
Thread-1:状态: java.lang.Object@20a5a1a4上的BLOCKED, 拥有者: Thread-0
Thread-2:状态: java.lang.Object@20a5a1a4上的BLOCKED, 拥有者: Thread-0
jstack工具
在终端输入命令:
jps
1488 Launcher 1489 SynchronizedTest 1491 Jps 500 570 RemoteMavenServer36 814 KotlinCompileDaemon
在终端输入命令:
jstack 1489
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.221-b11 mixed mode): "Thread-2" #21 prio=5 os_prio=31 tid=0x00007f968c0aa800 nid=0x9f03 waiting for monitor entry [0x0000700008441000] java.lang.Thread.State: BLOCKED (on object monitor) at com.tuyrk.chapter07.SynchronizedTest.lambda$main$0(SynchronizedTest.java:18) - waiting to lock <0x000000076adb5948> (a java.lang.Object) at com.tuyrk.chapter07.SynchronizedTest$$Lambda$1/500977346.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) "Thread-1" #20 prio=5 os_prio=31 tid=0x00007f968c0a9800 nid=0x6a03 waiting for monitor entry [0x000070000833e000] java.lang.Thread.State: BLOCKED (on object monitor) at com.tuyrk.chapter07.SynchronizedTest.lambda$main$0(SynchronizedTest.java:18) - waiting to lock <0x000000076adb5948> (a java.lang.Object) at com.tuyrk.chapter07.SynchronizedTest$$Lambda$1/500977346.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) "Thread-0" #19 prio=5 os_prio=31 tid=0x00007f968c0a9000 nid=0x6903 waiting on condition [0x000070000823b000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at com.tuyrk.chapter07.SynchronizedTest.lambda$main$0(SynchronizedTest.java:18) - locked <0x000000076adb5948> (a java.lang.Object) at com.tuyrk.chapter07.SynchronizedTest$$Lambda$1/500977346.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) "Monitor Ctrl-Break" #5 daemon prio=5 os_prio=31 tid=0x00007f9690127000 nid=0x3c03 runnable [0x000070000730e000] java.lang.Thread.State: RUNNABLE
线程锁LOCK即为MONITOR(监视器)
汇编指令
在终端输入命令:
javap -c 01-thread-base/target/classes/com/tuyrk/chapter07/TicketWindowRunnable.class
Compiled from "TicketWindowRunnable.java" public class com.tuyrk.chapter07.TicketWindowRunnable implements java.lang.Runnable { public com.tuyrk.chapter07.TicketWindowRunnable(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: iconst_1 6: putfield #2 // Field index:I 9: aload_0 10: new #3 // class java/lang/Object 13: dup 14: invokespecial #1 // Method java/lang/Object."<init>":()V 17: putfield #4 // Field MONITOR:Ljava/lang/Object; 20: return public void run(); Code: 0: aload_0 1: getfield #4 // Field MONITOR:Ljava/lang/Object; 4: dup 5: astore_1 6: monitorenter 7: aload_0 8: getfield #2 // Field index:I 11: sipush 500 14: if_icmple 22 17: aload_1 18: monitorexit 19: goto 93 22: ldc2_w #6 // long 5l 25: invokestatic #8 // Method java/lang/Thread.sleep:(J)V 28: goto 36 31: astore_2 32: aload_2 33: invokevirtual #10 // Method java/lang/InterruptedException.printStackTrace:()V 36: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream; 39: new #12 // class java/lang/StringBuilder 42: dup 43: invokespecial #13 // Method java/lang/StringBuilder."<init>":()V 46: invokestatic #14 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread; 49: invokevirtual #15 // Method java/lang/Thread.getName:()Ljava/lang/String; 52: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 55: ldc #17 // String 的号码是: 57: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 60: aload_0 61: dup 62: getfield #2 // Field index:I 65: dup_x1 66: iconst_1 67: iadd 68: putfield #2 // Field index:I 71: invokevirtual #18 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 74: invokevirtual #19 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 77: invokevirtual #20 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 80: aload_1 81: monitorexit 82: goto 90 85: astore_3 86: aload_1 87: monitorexit 88: aload_3 89: athrow 90: goto 0 93: return Exception table: from to target type 22 28 31 Class java/lang/InterruptedException 7 19 85 any 22 82 85 any 85 88 85 any }
getfield、putfield
monitorenter、monitorexit
javap --help
用法: javap <options> <classes>
其中, 可能的选项包括:
-help --help -? 输出此用法消息
-version 版本信息
-v -verbose 输出附加信息
-l 输出行号和本地变量表
-public 仅显示公共类和成员
-protected 显示受保护的/公共类和成员
-package 显示程序包/受保护的/公共类
和成员 (默认)
-p -private 显示所有类和成员
-c 对代码进行反汇编
-s 输出内部类型签名
-sysinfo 显示正在处理的类的
系统信息 (路径, 大小, 日期, MD5 散列)
-constants 显示最终常量
-classpath <path> 指定查找用户类文件的位置
-cp <path> 指定查找用户类文件的位置
-bootclasspath <path> 覆盖引导类文件的位置
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 tuyrk@qq.com
文章标题:119-结合jconsole,jstack以及汇编指令认识synchronized关键字
文章字数:1.1k
本文作者:神秘的小岛岛
发布时间:2019-11-24, 17:10:49
最后更新:2019-11-30, 14:39:44
原始链接:https://www.tuyrk.cn/wang-thread/119-synchronized/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。