2013-03-31 92 views

回答

6

它進入Foo.class對象的監視器。如果另一個方法也在Foo.Class上同步,則它將不得不等待,假設它在不同的線程中。

如果一個方法不同步它,那麼它將不受影響,不管它是否是靜態的。不是那些同步的靜態方法隱式地在它們被定義的類的類對象上同步。

0

它同步對使用它的方法/同步子句的訪問。這些可以是Bar類的方法 - 不一定是Foo。

重要的是,在「Foo.class」上同步的所有方法/同步子句不能同時執行。

同步完全不影響字段 - 無法聲明字段同步。

-1

我對tutorial​​3210的解釋只會鎖定類的靜態成員。但要確定你需要寫一個測試。

public class SyncTest { 
    public static SyncTest instance; 
    public static String valueA; 
    public String valueB; 

    public static void main(String[] args) { 
     instance = new SyncTest(); 

     (new Thread(new Task1())).start(); 
     (new Thread(new Task2())).start(); 
     try { 
      Thread.sleep(10000); 
      synchronized(SyncTest.class) { 
       System.out.println("Value A: " + valueA); 
      } 
      synchronized(instance) { 
       System.out.println("Value B: " + instance.valueB); 
      } 
     } catch (InterruptedException interrupt) { } 
    } 
} 

class Task1 implements Runnable { 
    public void run() { 
     try { 
      synchronized(SyncTest.class) { 
       System.out.println("Task 1 Sleeping "); 
       Thread.sleep(500); 
       SyncTest.valueA = "One"; 
       System.out.println("T1 A: " + SyncTest.valueA); 
      } 

      synchronized(SyncTest.instance) { 
       Thread.sleep(1000); 
       SyncTest.instance.valueB = "Two"; 
       System.out.println("T1 B: " + SyncTest.instance.valueB); 
      } 
     } catch (InterruptedException interrupt) { } 
     System.out.println("Task 1 Finished "); 
    } 
} 

class Task2 implements Runnable { 
    public void run() { 
     System.out.println("Task 2 Started"); 
     try { 
      Thread.sleep(1000); 
      synchronized(SyncTest.class) { 
       SyncTest.instance.valueB = "Four"; 
       System.out.println("T2 B: " + SyncTest.instance.valueB); 

       Thread.sleep(5000); 

       SyncTest.valueA = "Three"; 
       System.out.println("T2 A: " + SyncTest.valueA); 
      } 
     } catch (InterruptedException interrupt) { } 
     System.out.println("Task 2 Finished"); 
    } 
} 

這給輸出:

Task 1 Sleeping 
Task 2 Started 
T1 A: One 
T2 B: Four 
T1 B: Two 
Task 1 Finished 
T2 A: Three 
Task 2 Finished 
Value A: Three 
Value B: Two 

由於任務2更新valueB而任務1持有實例鎖我認爲,這顯示靜態鎖不鎖類的所有實例。

+0

它不鎖定任何成員。它根本不鎖定任何東西。它*在類對象上同步*。 – EJP

1

類對象的同步與實例的同步完全一樣。類如Foo.class是一個對象,因此具有內置監視器。您提供的代碼:

synchronized(Foo.Class){ 
    //some code.. 
} 

同步訪問Foo類。嘗試同步類的靜態變量時可能很有用。例如:

public class Foo{ 

    private static int COUNTER = 0; 

    synchronized public static void increment(){ 

     COUNTER ++; 
    } 

    public static void decrement(){ 
     synchronized (Foo.class) { 

      COUNTER ++; 
     } 
    } 
} 

正如你可以看到,可以實現相同的Foo.class同步作爲任何實例。當試圖同步實例的代碼塊時,使用:synchronized(this){},在類對象的情況下相當於synchronized(Foo.class){}。這同樣適用於同步方法的情況下:synchronized public void increment(){}相當於:synchronized public static void increment(){}

現在關於你的問題:

這是否鎖定Foo類的所有實例或僅是靜態 方法/字段?

當然,它並不像上面解釋的那樣獲取所有實例的鎖。此外,類對象不知道創建的實例。 A​​塊不鎖定字段。它只鎖定一塊代碼/方法,它被獲取該鎖的線程強制作爲原子操作執行,並且沒有其他線程可以進入該代碼塊(但是如果它們不同步,則可以執行其他塊),直到第一個線程釋放該鎖(其在Java中是大括號的末尾})。