2011-07-07 93 views
0

例1)多線程鎖方法

​​

例2)

public class MsLunch { 
    private long c1 = 0; 
    private long c2 = 0; 
    private Object lock1 = new Object(); 
    private Object lock2 = new Object(); 

    public void inc1() { 
     synchronized(lock1) { 
      c1++; 
     } 
    } 

    public void inc2() { 
     synchronized(lock2) { 
      c2++; 
     } 
    } 
} 

我從Java網站這兩個Java代碼,但我不很清楚地看到這兩者之間的區別。你們可以給我更多的解釋,我應該交替使用這種情況嗎?在此先感謝

+0

Eh。有點不清楚你想要什麼?這兩個snipets只是使用同步的例子。第一個不太好,因爲使用_this_進行同步從訪問角度來看是不安全的 – evilcroco

回答

2

有兩點不同:

  • this而不是私人蔘考第一個例子鎖。我認爲這是一般一個壞主意 - 這意味着其他代碼可以鎖定在同一個顯示器,這使得它更難於來思考你的代碼。除非你想其他代碼,能夠獲得一臺監視器上的鎖(在這種情況下,我通常暴露顯示器明確爲目的),爲什麼把自己在其他代碼擺佈?在大多數情況下,鎖應該是實現細節,但將其作爲公共參考(其實有效地使用this)會使該實現細節對全世界可見。
  • 第二個示例顯示在不同的引用同一類內鎖定兩個方法。這意味着兩個線程可以同時調用inc1inc2。如果有在第一個例子中的多種方法,都鎖定於this,那麼只有一個線程可以在同一時間進入這些方法的任何

我通常使用一個單一的鎖適用於所有的單一類中除非我有充分的理由相信,將是大量的類的狀態只有部分獨立工作的操作 - 其中這表明該班可能太大而無法入門。

我也使我的「鎖變量」最終,因爲你幾乎永不希望能夠改變他們在一個對象的生命週期。

所以,如果我真的使用的鎖,我可能會寫出來的第二個例子是:

public class MsLunch { 
    private long c1 = 0; 
    private long c2 = 0; 
    private final Object lock = new Object(); 

    public void inc1() { 
     synchronized(lock) { 
      c1++; 
     } 
    } 

    public void inc2() { 
     synchronized(lock) { 
      c2++; 
     } 
    } 
} 

不過,我倒是考慮:

  • 不要使實例方法以線程安全方式開始。我發現很少有一個類的單個實例會同時從多個線程中使用。 (靜態方法通常應該是線程安全的,但。)
  • 使用AtomicLong,而不是鎖定。通常使用更高級別的概念而不是線程原語可以使您的代碼更容易理解更高效。
+0

@fiver:不同之處在於其他代碼可以看到引用並可能鎖定它。這是一個巨大的差異。 –

0

在您正在同步this對象上的第一個例子(實際類對象,這是在大多數情況下足夠,認爲這是一種粗晶鎖。

在第二個示例中,您鎖定創建的對象的唯一目的是鎖定。這種方法可以讓你對鎖定有更精細的控制(在這種情況下,同時有兩個鎖,類對象不會被鎖定)

另外,如果你使用synchronize方法,它很漂亮與在this對象上的同步非常相似。基本上它們是可以互換的,但是您可能更喜歡根據您的情況進行鎖定控制。

+0

由於我的文章中描述的原因,我認爲同步「this」是一個糟糕的想法 - 同步應該幾乎總是一個實現細節,所以爲什麼要在公開可用的監視器上同步? –

+0

在問題中顯示的兩個示例代碼的上下文中,它們是可互換的。在更復雜的大型系統中,由於您提到的原因(其他代碼可公開提供),您可能希望避免鎖定此係統。 –

+0

它們不可互換 - 顯然*任何*交互將取決於調用代碼,並且如果某些外部代碼決定鎖定對象的監視器,則行爲會有很大差異。 –