Some differences between Synchronized decorating method and code block at the bottom

Article catalog Decorated code block Modify instance method Modifying static methods summary Decorated code block ...
Decorated code block
Modify instance method
Modifying static methods
summary

Article catalog

Decorated code block

The above example:

public class SyncCodeBlock { public int i; public void syncTask(){ //Sync codebase synchronized (this){ i++; } } }

Compile with javac and view bytecode with 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."<init>":()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 <init> #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 // "<init>":()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."<init>":()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"

The JVM synchronizes code blocks by entering and exiting the object Monitor.

Modify instance method

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 new instance Thread t1 = new Thread(new SyncInstance()); //New new instance t1.start(); //Join meaning: the current thread A waits for the thread to terminate before it can start thread.join() return t1.join(); } }

To view its bytecode:

$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."<init>":()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."<init>":()V #7 = Methodref #4.#33 // java/lang/Thread."<init>":(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 <init> #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 <clinit> #26 = Utf8 SourceFile #27 = Utf8 SyncInstance.java #28 = NameAndType #14:#15 // "<init>":()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 // "<init>":(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."<init>":()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 "<init>":()V 11: invokespecial #7 // Method java/lang/Thread."<init>":(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"

The synchronized decorated instance method does not have the monitorenter and monitorexit instructions, but acc_ The synchronized ID indicates that the method is a synchronization method, and the JVM uses the ACC_ The synchronized access flag is used to identify whether a method is declared as a synchronous method, so as to execute the corresponding synchronous call;

Modifying static methods

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 new instance Thread t1 = new Thread(new SynStatic()); //New new instance t1.start(); //Join meaning: the current thread A waits for the thread to terminate before starting thread.join() return t1.join(); } }

To view its bytecode:

$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."<init>":()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."<init>":()V #7 = Methodref #4.#33 // java/lang/Thread."<init>":(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 <init> #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 <clinit> #26 = Utf8 SourceFile #27 = Utf8 SynStatic.java #28 = NameAndType #14:#15 // "<init>":()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 // "<init>":(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."<init>":()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 "<init>":()V 11: invokespecial #7 // Method java/lang/Thread."<init>":(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"

The static method modified by synchronized does not have the monitorenter instruction and monitorexit instruction. Instead, ACC is used to get_ Synchronized identification;

summary

When synchronized decorates a code block:
The implementation of synchronous statement block uses the monitorenter and monitorexit instructions, in which the monitorenter instruction points to the start position of synchronous code block and the monitorexit instruction indicates the end position of synchronous code block;
When the synchronized modifier is used:
Instead of the monitorenter and monitorexit instructions, the synchronized decorated method is acc_ The synchronized ID indicates that the method is a synchronization method, and the JVM uses the ACC_ The synchronized access flag is used to identify whether a method is declared as a synchronized method, so as to execute the corresponding synchronized call.


27 June 2020, 02:14 | Views: 7769

Add new comment

For adding a comment, please log in
or create account

0 comments