我會嘗試通過以下三種情況來解釋這個問題。 案例一: 我是用使用這樣的同步共享鎖:使用本地鎖而不是共享鎖進行同步安全嗎?
private static final String SHARED_LOCK = "shared_lock";
private static int i = 0;
private static int j = 0;
void increment() {
synchronized (SHARED_LOCK) {
i++;
j++;
}
}
而且這是工作的罰款。
案例二: 現在我已經在這改變是不是使用共享鎖,我做這樣的事情想使用本地鎖:
private static int i = 0;
private static int j = 0;
void increment() {
final String LOCAL_LOCK = "local_lock";
synchronized (LOCAL_LOCK) {
i++;
j++;
}
}
而且我發現代碼仍然是工作罰款是同步仍在工作。
案例三: 然而,當我改變了當地LOCL這樣:
final String LOCAL_LOCK = new String("local_lock");
然後同步走了。所以看起來在CASE II中,本地鎖能夠提供同步,因爲Java會爲我們自動執行String實例,但是在CASE III中,我每次都明確地創建一個新的String,因此沒有發生同步。
所以回到我原來的問題。有沒有人認爲CASE II不是實現同步的正確方法?如果是的話,請你也提一下爲什麼?
在此先感謝, SacTiw。
所以在這裏你的意思是情況2可能會導致一些其他線程訪問其他類可能會開始使用相同的鎖作爲這個類,這將導致性能差和痛苦的調試。對? – sactiw 2010-08-12 09:57:12
在Java語言規範中提到,在Java中,不同包中不同類中的文字字符串(不可變)同樣代表對同一個字符串對象的引用。這個規則適用於所有原始對象,因爲它們都是不可變的。 因此,這意味着如果我們按情況2行事,可能導致性能下降,並在面臨死鎖時進行痛苦的調試。 所以我認爲我可以說,我的問題可以通過案例2進行同步,但它並不是所有推薦的使用方式。 – sactiw 2010-08-12 14:24:19
絕對,sactiw。使用除私有的,不可訪問的其他類對象以外的任何東西通常是一個非常糟糕的主意。如果你通過'new'得到一個對象,你就知道它是你自己的(只要你不泄漏它)。 – Cowan 2010-08-12 21:04:35