Java 中的物件鎖和類鎖有什麼區別?


物件鎖和類鎖都用於在多執行緒應用程式中實現同步機制。

物件鎖

Java 中的每個物件都有一個唯一的鎖。如果一個執行緒想要執行給定物件上的同步方法,首先它必須獲得該物件的鎖。一旦執行緒獲得了鎖,它就可以執行該物件上的任何同步方法。方法執行完成後,執行緒會自動釋放鎖。

鎖的獲取和釋放由 JVM 內部處理。當我們想要同步非靜態方法或非靜態程式碼塊時,物件鎖是一種機制,這樣只有一個執行緒能夠在類的給定例項上執行程式碼塊。這始終可以用來使例項級資料執行緒安全。

示例

public class ObjectLevelLockTest implements Runnable {
   @Override
   public void run() {
      objectLock();
   }
   public void objectLock() {
      System.out.println(Thread.currentThread().getName());
      synchronized(this) {
         System.out.println("Synchronized block " + Thread.currentThread().getName());
         System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");
      }
   }
   public static void main(String[] args) {
      ObjectLevelLockTest test1 = new ObjectLevelLockTest();
      Thread t1 = new Thread(test1);
      Thread t2 = new Thread(test1);
      ObjectLevelLockTest test2 = new ObjectLevelLockTest();
      Thread t3 = new Thread(test2);
      t1.setName("t1");
      t2.setName("t2");
      t3.setName("t3");
      t1.start();
      t2.start();
      t3.start();
   }
}

輸出

t1
t2
t3
Synchronized block t1
Synchronized block t3
Synchronized block t1 end
Synchronized block t2
Synchronized block t3 end
Synchronized block t2 end

類鎖

Java 中的每個類都有一個唯一的鎖,它就是類鎖。如果一個執行緒想要執行靜態同步方法,則該執行緒需要類鎖。一旦執行緒獲得了類鎖,它就可以執行該類的任何靜態同步方法。

方法執行完成後,執行緒會自動釋放鎖。類鎖可以防止多個執行緒在執行時任何可用例項的同步塊中進入。

示例

public class ClassLevelLockTest implements Runnable {
   @Override
   public void run() {
      classLock();
   }
   public void classLock() {
      System.out.println(Thread.currentThread().getName());
      synchronized(ClassLevelLockTest.class) {
         System.out.println("Synchronized block " + Thread.currentThread().getName());
         System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");
      }
   }
   public static void main(String[] args) {
      ClassLevelLockTest test1 = new ClassLevelLockTest();
      Thread t1 = new Thread(test1);
      Thread t2 = new Thread(test1);
      ClassLevelLockTest test2 = new ClassLevelLockTest();
      Thread t3 = new Thread(test2);
      t1.setName("t1");
      t2.setName("t2");
      t3.setName("t3");
      t1.start();
      t2.start();
      t3.start();
   }
}

輸出

t1
t2
t3
Synchronized block t1
Synchronized block t1 end
Synchronized block t3
Synchronized block t3 end
Synchronized block t2
Synchronized block t2 end

更新於: 2023-11-28

5K+ 瀏覽量

開啟您的 職業生涯

透過完成課程獲得認證

開始學習
廣告