上例子:
public class SyncCodeBlock {
public int i;
public void syncTask(){
//同步代码库
synchronized (this){
i++;
}
}
}
使用javac编译,使用javap查看字节码:
$javac SyncCodeBlock.java
$javap -v -c -s -l SyncCodeBlock.class
Classfile /Users/mac/IdeaProjects/multiThread/src/main/java/ThreadBasic/Synchronized/SyncCodeBlock.class
Last modified 2020-6-26; size 427 bytes
MD5 checksum 46c58b50c71e6579e6e3d8b903ac2680
Compiled from "SyncCodeBlock.java"
public class ThreadBasic.Synchronized.SyncCodeBlock
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #4.#18 // java/lang/Object."":()V
#2 = Fieldref #3.#19 // ThreadBasic/Synchronized/SyncCodeBlock.i:I
#3 = Class #20 // ThreadBasic/Synchronized/SyncCodeBlock
#4 = Class #21 // java/lang/Object
#5 = Utf8 i
#6 = Utf8 I
#7 = Utf8
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 syncTask
#12 = Utf8 StackMapTable
#13 = Class #20 // ThreadBasic/Synchronized/SyncCodeBlock
#14 = Class #21 // java/lang/Object
#15 = Class #22 // java/lang/Throwable
#16 = Utf8 SourceFile
#17 = Utf8 SyncCodeBlock.java
#18 = NameAndType #7:#8 // "":()V
#19 = NameAndType #5:#6 // i:I
#20 = Utf8 ThreadBasic/Synchronized/SyncCodeBlock
#21 = Utf8 java/lang/Object
#22 = Utf8 java/lang/Throwable
{
public int i;
descriptor: I
flags: ACC_PUBLIC
public ThreadBasic.Synchronized.SyncCodeBlock();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 3: 0
public void syncTask();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=3, args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: aload_0
5: dup
6: getfield #2 // Field i:I
9: iconst_1
10: iadd
11: putfield #2 // Field i:I
14: aload_1
15: monitorexit
16: goto 24
19: astore_2
20: aload_1
21: monitorexit
22: aload_2
23: athrow
24: return
Exception table:
from to target type
4 16 19 any
19 22 19 any
LineNumberTable:
line 9: 0
line 10: 4
line 11: 14
line 12: 24
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 19
locals = [ class ThreadBasic/Synchronized/SyncCodeBlock, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
}
SourceFile: "SyncCodeBlock.java"
JVM 是通过进入、退出对象监视器( Monitor )来实现对代码块的同步的。
public class SyncInstance implements Runnable{
static int i = 0;
public synchronized void increase() {
i++;
}
@Override
public void run() {
for (int j = 0; j < 5; j++) {
increase();
}
}
public static void main(String[] args) throws InterruptedException {
//new新实例
Thread t1 = new Thread(new SyncInstance());
//new新实例
t1.start();
//join含义:当前线程A等待thread线程终止之后才能从thread.join()返回
t1.join();
}
}
查看其字节码:
$javac SyncInstance.java
$javap -v -c -s -l SyncInstance.class
Classfile /Users/mac/IdeaProjects/multiThread/src/main/java/ThreadBasic/Synchronized/SyncInstance.class
Last modified 2020-6-26; size 769 bytes
MD5 checksum 4bc0bc765b64da5799760cf7a04b01cc
Compiled from "SyncInstance.java"
public class ThreadBasic.Synchronized.SyncInstance implements java.lang.Runnable
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #10.#28 // java/lang/Object."":()V
#2 = Fieldref #5.#29 // ThreadBasic/Synchronized/SyncInstance.i:I
#3 = Methodref #5.#30 // ThreadBasic/Synchronized/SyncInstance.increase:()V
#4 = Class #31 // java/lang/Thread
#5 = Class #32 // ThreadBasic/Synchronized/SyncInstance
#6 = Methodref #5.#28 // ThreadBasic/Synchronized/SyncInstance."":()V
#7 = Methodref #4.#33 // java/lang/Thread."":(Ljava/lang/Runnable;)V
#8 = Methodref #4.#34 // java/lang/Thread.start:()V
#9 = Methodref #4.#35 // java/lang/Thread.join:()V
#10 = Class #36 // java/lang/Object
#11 = Class #37 // java/lang/Runnable
#12 = Utf8 i
#13 = Utf8 I
#14 = Utf8
#15 = Utf8 ()V
#16 = Utf8 Code
#17 = Utf8 LineNumberTable
#18 = Utf8 increase
#19 = Utf8 run
#20 = Utf8 StackMapTable
#21 = Utf8 main
#22 = Utf8 ([Ljava/lang/String;)V
#23 = Utf8 Exceptions
#24 = Class #38 // java/lang/InterruptedException
#25 = Utf8
#26 = Utf8 SourceFile
#27 = Utf8 SyncInstance.java
#28 = NameAndType #14:#15 // "":()V
#29 = NameAndType #12:#13 // i:I
#30 = NameAndType #18:#15 // increase:()V
#31 = Utf8 java/lang/Thread
#32 = Utf8 ThreadBasic/Synchronized/SyncInstance
#33 = NameAndType #14:#39 // "":(Ljava/lang/Runnable;)V
#34 = NameAndType #40:#15 // start:()V
#35 = NameAndType #41:#15 // join:()V
#36 = Utf8 java/lang/Object
#37 = Utf8 java/lang/Runnable
#38 = Utf8 java/lang/InterruptedException
#39 = Utf8 (Ljava/lang/Runnable;)V
#40 = Utf8 start
#41 = Utf8 join
{
static int i;
descriptor: I
flags: ACC_STATIC
public ThreadBasic.Synchronized.SyncInstance();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 3: 0
public synchronized void increase();
descriptor: ()V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field i:I
3: iconst_1
4: iadd
5: putstatic #2 // Field i:I
8: return
LineNumberTable:
line 7: 0
line 8: 8
public void run();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: iconst_5
4: if_icmpge 17
7: aload_0
8: invokevirtual #3 // Method increase:()V
11: iinc 1, 1
14: goto 2
17: return
LineNumberTable:
line 12: 0
line 13: 7
line 12: 11
line 15: 17
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 2
locals = [ int ]
frame_type = 250 /* chop */
offset_delta = 14
public static void main(java.lang.String[]) throws java.lang.InterruptedException;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=2, args_size=1
0: new #4 // class java/lang/Thread
3: dup
4: new #5 // class ThreadBasic/Synchronized/SyncInstance
7: dup
8: invokespecial #6 // Method "":()V
11: invokespecial #7 // Method java/lang/Thread."":(Ljava/lang/Runnable;)V
14: astore_1
15: aload_1
16: invokevirtual #8 // Method java/lang/Thread.start:()V
19: aload_1
20: invokevirtual #9 // Method java/lang/Thread.join:()V
23: return
LineNumberTable:
line 19: 0
line 21: 15
line 23: 19
line 24: 23
Exceptions:
throws java.lang.InterruptedException
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: iconst_0
1: putstatic #2 // Field i:I
4: return
LineNumberTable:
line 4: 0
}
SourceFile: "SyncInstance.java"
synchronized修饰的实例方法并没有monitorenter指令和monitorexit指令,取而代之的是ACC_SYNCHRONIZED标识,该标识指明了该方法是一个同步方法,JVM通过该ACC_SYNCHRONIZED访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用;
package ThreadBasic.Synchronized;
public class SynStatic implements Runnable {
static int i = 0;
public static synchronized void increase() {
i++;
}
@Override
public void run() {
for (int j = 0; j < 5; j++) {
increase();
}
}
public static void main(String[] args) throws InterruptedException {
//new新实例
Thread t1 = new Thread(new SynStatic());
//new新实例
t1.start();
//join含义:当前线程A等待thread线程终止之后才能从thread.join()返回
t1.join();
}
}
查看其字节码:
$javac SynStatic.java
$javap -c -v -s -l SynStatic.class
Classfile /Users/mac/IdeaProjects/multiThread/src/main/java/ThreadBasic/Synchronized/SynStatic.class
Last modified 2020-6-26; size 762 bytes
MD5 checksum f66c06958c4b1a7b9e84d47933cc6dda
Compiled from "SynStatic.java"
public class ThreadBasic.Synchronized.SynStatic implements java.lang.Runnable
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #10.#28 // java/lang/Object."":()V
#2 = Fieldref #5.#29 // ThreadBasic/Synchronized/SynStatic.i:I
#3 = Methodref #5.#30 // ThreadBasic/Synchronized/SynStatic.increase:()V
#4 = Class #31 // java/lang/Thread
#5 = Class #32 // ThreadBasic/Synchronized/SynStatic
#6 = Methodref #5.#28 // ThreadBasic/Synchronized/SynStatic."":()V
#7 = Methodref #4.#33 // java/lang/Thread."":(Ljava/lang/Runnable;)V
#8 = Methodref #4.#34 // java/lang/Thread.start:()V
#9 = Methodref #4.#35 // java/lang/Thread.join:()V
#10 = Class #36 // java/lang/Object
#11 = Class #37 // java/lang/Runnable
#12 = Utf8 i
#13 = Utf8 I
#14 = Utf8
#15 = Utf8 ()V
#16 = Utf8 Code
#17 = Utf8 LineNumberTable
#18 = Utf8 increase
#19 = Utf8 run
#20 = Utf8 StackMapTable
#21 = Utf8 main
#22 = Utf8 ([Ljava/lang/String;)V
#23 = Utf8 Exceptions
#24 = Class #38 // java/lang/InterruptedException
#25 = Utf8
#26 = Utf8 SourceFile
#27 = Utf8 SynStatic.java
#28 = NameAndType #14:#15 // "":()V
#29 = NameAndType #12:#13 // i:I
#30 = NameAndType #18:#15 // increase:()V
#31 = Utf8 java/lang/Thread
#32 = Utf8 ThreadBasic/Synchronized/SynStatic
#33 = NameAndType #14:#39 // "":(Ljava/lang/Runnable;)V
#34 = NameAndType #40:#15 // start:()V
#35 = NameAndType #41:#15 // join:()V
#36 = Utf8 java/lang/Object
#37 = Utf8 java/lang/Runnable
#38 = Utf8 java/lang/InterruptedException
#39 = Utf8 (Ljava/lang/Runnable;)V
#40 = Utf8 start
#41 = Utf8 join
{
static int i;
descriptor: I
flags: ACC_STATIC
public ThreadBasic.Synchronized.SynStatic();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 3: 0
public static synchronized void increase();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=0, args_size=0
0: getstatic #2 // Field i:I
3: iconst_1
4: iadd
5: putstatic #2 // Field i:I
8: return
LineNumberTable:
line 7: 0
line 8: 8
public void run();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: iconst_5
4: if_icmpge 16
7: invokestatic #3 // Method increase:()V
10: iinc 1, 1
13: goto 2
16: return
LineNumberTable:
line 12: 0
line 13: 7
line 12: 10
line 15: 16
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 2
locals = [ int ]
frame_type = 250 /* chop */
offset_delta = 13
public static void main(java.lang.String[]) throws java.lang.InterruptedException;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=2, args_size=1
0: new #4 // class java/lang/Thread
3: dup
4: new #5 // class ThreadBasic/Synchronized/SynStatic
7: dup
8: invokespecial #6 // Method "":()V
11: invokespecial #7 // Method java/lang/Thread."":(Ljava/lang/Runnable;)V
14: astore_1
15: aload_1
16: invokevirtual #8 // Method java/lang/Thread.start:()V
19: aload_1
20: invokevirtual #9 // Method java/lang/Thread.join:()V
23: return
LineNumberTable:
line 19: 0
line 21: 15
line 23: 19
line 24: 23
Exceptions:
throws java.lang.InterruptedException
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: iconst_0
1: putstatic #2 // Field i:I
4: return
LineNumberTable:
line 4: 0
}
SourceFile: "SynStatic.java"
synchronized修饰的静态方法也没有monitorenter指令和monitorexit指令,取得代之的是ACC_SYNCHRONIZED标识;
synchronized修饰代码块的时候:
同步语句块的实现使用的是monitorenter 和 monitorexit 指令,其中monitorenter指令指向同步代码块的开始位置,monitorexit指令则指明同步代码块的结束位置;
synchronized修饰方法的时候:
synchronized修饰的方法并没有monitorenter指令和monitorexit指令,取而代之的是ACC_SYNCHRONIZED标识,该标识指明了该方法是一个同步方法,JVM通过该ACC_SYNCHRONIZED访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。