程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java多線程初學者指南(11):使用Synchronized塊同步方法

Java多線程初學者指南(11):使用Synchronized塊同步方法

編輯:關於JAVA

synchronized關鍵字有兩種用法。第一種就是在《使用Synchronized關鍵字同步類方法》一文中所介紹的直接用在方法的定義中。另外一種就是synchronized塊。我們不僅可以通過synchronized塊來同步一個對象變量。也可以使用synchronized塊來同步類中的靜態方法和非靜態方法。

synchronized塊的語法如下:

public void method()
{
… …
synchronized(表達式)
{
… …
}
}

一、非靜態類方法的同步

從《使用Synchronized關鍵字同步類方法》一文中我們知道使用synchronized關鍵字來定義方法就會鎖定類中所有使用synchronzied關鍵字定義的靜態方法或非靜態方法,但這並不好理解。而如果使用synchronized塊來達到同樣的效果,就不難理解為什麼會產生這種效果了。如果想使用synchronized塊來鎖定類中所有的同步非靜態方法,需要使用this做為synchronized塊的參數傳入synchronized塊國,代碼如下:

通過synchronized塊同步非靜態方法

001  public class SyncBlock
002  {
003      public void method1()
004      {
005          synchronized(this)  // 相當於對method1方法使用synchronized關鍵字
006          {
007              … …
008          }
009      }
010      public void method2()
011      {
012          synchronized(this)  // 相當於對method2方法使用synchronized關鍵字
013          {
014              … …
015          }
016      }
017      public synchronized void method3()
018      {
019          … …
020      }
021  }

在上面的代碼中的method1和method2方法中使用了synchronized塊。而第017行的method3方法仍然使用synchronized關鍵字來定義方法。在使用同一個SyncBlock類實例時,這三個方法只要有一個正在執行,其他兩個方法就會因未獲得同步鎖而被阻塞。在使用synchronized塊時要想達到和synchronized關鍵字同樣的效果,必須將所有的代碼都寫在synchronized塊中,否則,將無法使當前方法中的所有代碼和其他的方法同步。

除了使用this做為synchronized塊的參數外,還可以使用SyncBlock.this作為synchronized塊的參數來達到同樣的效果。

在內類(InnerClass)的方法中使用synchronized塊來時,this只表示內類,和外類(OuterClass)沒有關系。但內類的非靜態方法可以和外類的非靜態方法同步。如在內類InnerClass中加一個method4方法,並使method4方法和SyncBlock的三個方法同步,代碼如下:

使內類的非靜態方法和外類的非靜態方法同步

public class SyncBlock
{
… …
class InnerClass
{
public void method4()
{
synchronized(SyncBlock.this)
{
… … 
}
}
}
… …
}

在上面SyncBlock類的新版本中,InnerClass類的method4方法和SyncBlock類的其他三個方法同步,因此,method1、method2、method3和method4四個方法在同一時間只能有一個方法執行。

Synchronized塊不管是正常執行完,還是因為程序出錯而異常退出synchronized塊,當前的synchronized塊所持有的同步鎖都會自動釋放。因此,在使用synchronized塊時不必擔心同步鎖的釋放問題。

二、靜態類方法的同步

由於在調用靜態方法時,對象實例不一定被創建。因此,就不能使用this來同步靜態方法,而必須使用Class對象來同步靜態方法。代碼如下:

通過synchronized塊同步靜態方法

public class StaticSyncBlock
{
public static void method1()
{
synchronized(StaticSyncBlock.class)
{
… …
}
}
public static synchronized void method2()
{
… …
}
}

在同步靜態方法時可以使用類的靜態字段class來得到Class對象。在上例中method1和method2方法同時只能有一個方法執行。除了使用class字段得到Class對象外,還可以使用實例的getClass方法來得到Class對象。上例中的代碼可以修改如下:

使用getClass方法得到Class對象

public class StaticSyncBlock
{
public static StaticSyncBlock instance; 
public StaticSyncBlock()
{
instance = this;
}
public static void method1()
{
synchronized(instance.getClass())
{
 
}
}
 
}

在上面代碼中通過一個public的靜態instance得到一個StaticSyncBlock類的實例,並通過這個實例的getClass方法得到了Class對象(一個類的所有實例通過getClass方法得到的都是同一個Class對象,因此,調用任何一個實例的getClass方法都可以)。我們還可以通過Class對象使不同類的靜態方法同步,如Test類的靜態方法method和StaticSyncBlock類的兩個靜態方法同步,代碼如下:

Test類的method方法和StaticSyncBlock類的method1、method2方法同步

public class Test
{
public static void method()
{
synchronized(StaticSyncBlock.class)
{
 
}
}
}

注意:在使用synchronized塊同步類方法時,非靜態方法可以使用this來同步,而靜態方法必須使用Class對象來同步。它們互不影響。當然,也可以在非靜態方法中使用Class對象來同步靜態方法。但在靜態方法中不能使用this來同步非靜態方法。這一點在使用synchronized塊同步類方法時應注意。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved