synchronized關鍵字的作用是什么?


Java 中關鍵字 synchronized 表示只有一個線程可以獲取作用對象的鎖,執行代碼,阻塞其他線程。

作用:

  • 確保線程互斥地訪問同步代碼
  • 保證共享變量的修改能夠及時可見
  • 有效解決重排序問題

 

用法:

  • 修飾普通方法
  • 修飾靜態方法
  • 指定對象,修飾代碼塊

 

特點:

  • 阻塞未獲取到鎖、競爭同一個對象鎖的線程
  • 獲取鎖無法設置超時
  • 無法實現公平鎖
  • 控制等待和喚醒需要結合加鎖對象的 wait() 和 notify()、notifyAll()
  • 鎖的功能是 JVM 層面實現的
  • 在加鎖代碼塊執行完或者出現異常,自動釋放鎖

 

原理:

  • 同步代碼塊是通過 monitorenter 和 monitorexit 指令獲取線程的執行權
  • 同步方法通過加 ACC_SYNCHRONIZED 標識實現線程的執行權的控制

 

測試代碼:

public class TestSynchronized {
	
	public void sync() {
		synchronized (this) {
			System.out.println("sync");
		}
	}
	
	public synchronized void syncdo() {
		System.out.println("syncdo");
	}
	
	public static synchronized void staticSyncdo() {
		System.out.println("staticSyncdo");
	}
}

 

通過JDK 反匯編指令 javap -c -v TestSynchronized

javap -c -v TestSynchronized
 
  Last modified 2019-5-27; size 719 bytes
  MD5 checksum e5058a43e76fe1cff6748d4eb1565658
  Compiled from "TestSynchronized.java"
public class constxiong.interview.TestSynchronized
  minor version: 0
  major version: 49
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // constxiong/interview/TestSynchronized
   #2 = Utf8               constxiong/interview/TestSynchronized
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lconstxiong/interview/TestSynchronized;
  #14 = Utf8               sync
  #15 = Fieldref           #16.#18        // java/lang/System.out:Ljava/io/PrintStream;
  #16 = Class              #17            // java/lang/System
  #17 = Utf8               java/lang/System
  #18 = NameAndType        #19:#20        // out:Ljava/io/PrintStream;
  #19 = Utf8               out
  #20 = Utf8               Ljava/io/PrintStream;
  #21 = String             #14            // sync
  #22 = Methodref          #23.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #23 = Class              #24            // java/io/PrintStream
  #24 = Utf8               java/io/PrintStream
  #25 = NameAndType        #26:#27        // println:(Ljava/lang/String;)V
  #26 = Utf8               println
  #27 = Utf8               (Ljava/lang/String;)V
  #28 = Utf8               syncdo
  #29 = String             #28            // syncdo
  #30 = Utf8               staticSyncdo
  #31 = String             #30            // staticSyncdo
  #32 = Utf8               SourceFile
  #33 = Utf8               TestSynchronized.java
{
  public constxiong.interview.TestSynchronized();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lconstxiong/interview/TestSynchronized;
 
  public void sync();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
         1: dup
         2: astore_1
         3: monitorenter
         4: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
         7: ldc           #21                 // String sync
         9: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        12: aload_1
        13: monitorexit
        14: goto          20
        17: aload_1
        18: monitorexit
        19: athrow
        20: return
      Exception table:
         from    to  target type
             4    14    17   any
            17    19    17   any
      LineNumberTable:
        line 6: 0
        line 7: 4
        line 6: 12
        line 9: 20
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      21     0  this   Lconstxiong/interview/TestSynchronized;
 
  public synchronized void syncdo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #29                 // String syncdo
         5: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 12: 0
        line 13: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   Lconstxiong/interview/TestSynchronized;
 
  public static synchronized void staticSyncdo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #31                 // String staticSyncdo
         5: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 16: 0
        line 17: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
}
SourceFile: "TestSynchronized.java"

 


 


 

所有資源資源匯總於公眾號



 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM