天天看點

【Java -- 基礎】線程鎖:方法鎖、對象鎖、類鎖

前言

synchronized 用來處理多個線程同時通路同一個類的一個代碼塊、方法,甚至這個類。

(1)修飾代碼塊時,需要一個reference對象作為鎖的對象。

(2)修飾方法時,預設是目前對線作為鎖的對象。

(3)修飾類時,預設是目前類的Class對象作為鎖的對象。

1、方法鎖

通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。

synchronized 方法控制對類成員變量的通路:

每個類執行個體對應一把鎖,每個 synchronized 方法都必須獲得調用該方法的類執行個體的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法傳回時才将鎖釋放,此後被阻塞的線程方能獲得該鎖,重新進入可執行狀态。這種機制確定了同一時刻對于每一個類執行個體,其所有聲明為 synchronized 的成員函數中至多隻有一個處于可執行狀态,進而有效避免了類成員變量的通路沖突。

2、對象鎖

當一個對象中有同步方法或者同步塊,線程調用此對象進入該同步區域時,必須獲得對象鎖。如果此對象的對象鎖被其他調用者占用,則進入阻塞隊列,等待此鎖被釋放(同步塊正常傳回或者抛異常終止,由JVM自動釋放對象鎖)。

注意,方法鎖也是一種對象鎖。當一個線程通路一個帶 synchronized 方法時,由于對象鎖的存在,所有加 synchronized 的方法都不能被通路(前提是在多個線程調用的是同一個對象執行個體中的方法)。

對象鎖有兩種形式:

public class object {
  public synchronized void method(){
    System.out.println("我是對象鎖也是方法鎖");
  }
}      

另外一種是:

public class object {
  public void method(){
    synchronized(this){
      System.out.println("我是對象鎖");
    }
  }
}      

3、類鎖

一個class其中的靜态方法和靜态變量在記憶體中隻會加載和初始化一份,是以,一旦一個靜态的方法被申明為synchronized,此類的所有的執行個體化對象在調用該方法時,共用同一把鎖,稱之為類鎖。

public class object {
  public static synchronized void method(){
    System.out.println("我是第一種類鎖");
  }
}      
public class object {
  public void method(){
    synchronized (object.this) {
      System.out.println("我是第二種類鎖");
    }
  }
}