java多線程編程之使用Synchronized塊同步方法

synchronized塊來同步一個對象變量,也可使用synchronized塊來同步類中的靜態方法和非靜態方法,下面使用Synchronized塊同步方法

synchronized關鍵字有兩種用法。第一種就是在《使用Synchronized關鍵字同步類方法》一文中所介紹的直接用在方法的定義中。 另一種就是synchronized塊。咱們不只能夠經過synchronized塊來同步一個對象變量。也可使用synchronized塊來同步 類中的靜態方法和非靜態方法。
synchronized塊的語法以下:this

複製代碼 代碼以下:

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

1、非靜態類方法的同步  spa

從《使用Synchronized關鍵字同步類方法》一文中咱們知道使用synchronized關鍵字來定義方法就會鎖定類中全部使用 synchronzied關鍵字定義的靜態方法或非靜態方法,但這並很差理解。而若是使用synchronized塊來達到一樣的效果,就不難理解爲何 會產生這種效果了。若是想使用synchronized塊來鎖定類中全部的同步非靜態方法,須要使用this作爲synchronized塊的參數傳入 synchronized塊國,代碼以下:
經過synchronized塊同步非靜態方法code

複製代碼 代碼以下:

public class SyncBlock
   {
       public void method1()
       {
           synchronized(this)  // 至關於對method1方法使用synchronized關鍵字
           {
               … …
           }
       }
       public void method2()
       {
           synchronized(this)  // 至關於對method2方法使用synchronized關鍵字
           {
               … …
           }
       }
       public synchronized void method3() 
       {
           … …
       }
   }

在上面的代碼中的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類的其餘三個方法同步,所以,method一、method二、method3和method4四個方法在同一時間只能有一個方法執行。
Synchronized塊不論是正常執行完,仍是由於程序出錯而異常退出synchronized塊,當前的synchronized塊所持有的同步鎖都會自動釋放。所以,在使用synchronized塊時沒必要擔憂同步鎖的釋放問題。get

2、靜態類方法的同步
因爲在調用靜態方法時,對象實例不必定被建立。所以,就不能使用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對象it

複製代碼 代碼以下:

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類的method一、method2方法同步io

複製代碼 代碼以下:

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

           }
       }
   }

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

相關文章
相關標籤/搜索