3

我知道構造函數不能在Java中同步。這是否意味着,如果構造函數修改類中的靜態變量,並且可以從多個線程調用構造函數,那麼訪問需要同步,如圖所示?在構造函數中訪問共享靜態變量是否需要同步?

public class MyClass { 
    private static int count = 0; 

    public MyClass() { 
    synchronized(MyClass.class) { 
     count++; 
    } 
    ... 
    } 
} 
+2

你知道靜態的,可變的變量是代碼味道,對嗎? – 2012-03-01 19:58:29

+0

@LouisWasserman,我沒有意識到他們被認爲是一種氣味,但我現在就做。謝謝。 – 2012-03-01 20:06:41

+1

[這裏](http://code.google.com/p/google-singleton-detector/wiki/WhySingletonsAreControversial)是一個可能解釋_why_他們是代碼味道的引用。它着重於單例 - 這是靜態的一個特例 - 但這個問題更普遍適用。 – 2012-03-01 20:23:37

回答

8

絕對 - 畢竟,它的訪問共享資源,可能通過多線程。我個人只是使​​用AtomicInteger來代替。

public class MyClass { 
    private static final AtomicInteger count = new AtomicInteger(); 

    public MyClass() { 
    count.incrementAndGet(); 
    } 
} 

注意,我們現在可以把這些變量最終爲變量不改變價值,我們並不需要同步任何更多的爲java.util.concurrent.atomic類的整點是,他們可以無需額外的同步就可以自動使用。

即使你是在您需要同步的情況下,我不會用MyClass.class這樣做 - 這就是它的其他代碼可能會決定要同步的一個參考,所以你不能真正原因有關代碼更多。我會寫(同樣,只AtomicInteger是不是出於某種原因不夠好):

public class MyClass { 
    private static final Object countLock = new Object(); 
    private static int count = 0; 

    public MyClass() { 
    synchronized(countLock) { 
     count++; 
    } 
    ... 
    } 
} 

(在這種情況下,你想也想在countLock其他地方同步訪問count,甚至只是爲了讀書。 )

+0

+1非常好,非常完整的答案。 – 2012-03-01 20:12:11

+0

據推測'count'正在其他地方使用。在第二個示例中,您還希望在'countLock'上同步任何對'count'的讀取訪問。 – 2012-03-01 20:52:17

+0

@TedHopp:的確如此。將這樣編輯。 – 2012-03-01 20:55:48

1

某種形式的同步是必要的,這是行得通的,是的。它將完成與同步靜態方法相同的功能。您可以考慮改用AtomicInteger

1

對於這種情況,我建議你使用AtomicInteger

+0

我覺得有必要投入這個詞:「要被激怒!」 – Gray 2012-03-01 20:19:12

+0

@格雷 - 的確如此。但必須在信貸到期時給予貸款。這是一個很好的答案。 – 2012-03-01 20:49:09

+0

當然可以。這就是他爲什麼是John Skeet的原因。 – Gray 2012-03-01 20:51:34