1. 程式人生 > >Java基礎知識之synchronized同步方法、程式碼塊、靜態方法、靜態程式碼塊的區別

Java基礎知識之synchronized同步方法、程式碼塊、靜態方法、靜態程式碼塊的區別

      Java中的同步塊用synchronized標記,是同步在某個物件上,所有同步在一個物件上的同步塊在同一時刻只能被一個執行緒進入並執行操作,其他等待進入該同步塊的執行緒將被阻塞,直到執行該同步塊中的執行緒退出。 有四種不同的同步塊:

  1. 例項方法同步;
  2. 靜態方法同步;
  3. 例項方法中的同步塊;
  4. 靜態方法中的同步塊。

1.例項方法同步

  Java例項方法同步是同步在擁有該方法的物件上。這樣,每個例項其方法同步都同步在不同的物件上,即該方法所屬的例項。只有一個執行緒能夠在例項方法同步塊中執行。如果有多個例項存在,那麼一個執行緒一次可以在一個例項同步塊中執行操作。一個例項一個執行緒。示例程式碼:

public synchronized void add(int value){
    this.count += value;
}

2.靜態方法同步

  靜態方法的同步是指同步在該方法所在的類物件上。因為在Java虛擬機器中一個類只能對應一個類物件,所以同時只允許一個執行緒執行同一個類中的靜態同步方法。
  對於不同類中的靜態同步方法,一個執行緒可以執行每個類中的靜態同步方法而無需等待,一個類只能由一個執行緒同時執行。s示例程式碼:

public static synchronized void add(int value){
    count += value; // count位靜態變數
 }

3.例項方法中的同步塊

  在非同步的Java方法中的同步塊的例子如下所示:

public void add(int value){
    synchronized(this){
       this.count += value;
    }
}

  示例使用Java同步塊構造器來標記一塊程式碼是同步的。該程式碼在執行時和同步方法一樣。
  PS:注意Java同步塊構造器用括號將物件括起來。在上例中,使用了“this”,即為呼叫add方法的例項本身。在同步構造器中用括號括起來的物件叫做監視器物件。上述程式碼使用監視器物件同步,同步例項方法使用呼叫方法本身的例項作為監視器物件。 一次只有一個執行緒能夠在同步於同一個監視器物件的Java方法內執行。
  下面兩個例子都同步他們所呼叫的例項物件上,因此他們在同步的執行效果上是等效的。

public class MyClass {
 
   public synchronized void log1(String msg1, String msg2){
      log.writeln(msg1);
      log.writeln(msg2);
   }
 
   public void log2(String msg1, String msg2){
      synchronized(this){
         log.writeln(msg1);
         log.writeln(msg2);
      }
   }
}

  在上例中,每次只有一個執行緒能夠在兩個同步塊中任意一個方法內執行。如果第二個同步塊不是同步在this例項物件上,那麼兩個方法可以被執行緒同時執行。

4.靜態方法中的同步塊

  下面是兩個靜態方法同步的例子。這些方法同步在該方法所屬的類物件上。

public class MyClass {
    public static synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }
 
    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
          log.writeln(msg1);
          log.writeln(msg2);
       }
    }
}

  這兩個方法不允許同時被執行緒訪問。如果第二個同步塊不是同步在MyClass.class這個物件上。那麼這兩個方法可以同時被執行緒訪問。

5.synchronized(this)、synchronized(object)、synchronized(*.class)區別

  下面單獨對同步程式碼塊的三種同步寫法做一下區別:
(1)、synchronized(this)同步程式碼塊:1)對其它的synchronized同步方法或synchronized(this)同步程式碼塊呼叫是堵塞狀態;2)同一時間只有一個執行緒執行同一物件的synchronized同步方法中的程式碼;
(2)、synchronized(object)進行同步操作時,物件監視器必須是同一個物件。不是同一個,執行就是非同步執行了;
(3)、synchronized(*.class)程式碼塊的作用其實和synchronized static方法作用一樣。Class鎖對類其作用,也就是對類所有物件例項起作用。