2011-07-24 128 views
8

是否有人可以解釋的對象鎖定的情況下這兩個例子之間的區別:同步線程和鎖定

public void method1(){ 
    synchronized(this){ 
     .... 
    } 
} 

而且

StringBuffer aStringBufferObject = new StringBuffer("A"); 

public void method2(){ 
    synchronized(aStringBufferObject){ 
     .... 
    } 
} 

我所知道的第一個例子將獲取的鎖this實例,第二個將獲得aStringBufferObject實例的鎖定。但我真的不明白兩者的效果或差異。

例如,在第二個例子中,線程是否仍然能夠執行synchronized塊中的代碼,因爲鎖與'this'實例無關?

我知道同步一個方法或一段代碼可以防止多個線程同時訪問該塊/方法,但指定要鎖定的對象的目的是什麼以及對象的方式有什麼區別是在上面的例子中指定的?

+1

另請參見[同步方法和線程鎖定](http://forums.oracle.com/forums/thread.jspa?threadID=2257647)。 –

+0

也看看這裏:[Java併發/多線程 - 教程](http://www.vogella.de/articles/JavaConcurrency/article.html) –

+0

@Andrew:啊,我雖然你指的是一篇文章,但現在看看它是一個多文章。 –

回答

8

指定對象鎖定的目的是什麼?

通常情況下,更容易在this或在Class實例(靜態方法)同步。但是,有些情況下您需要在特定對象上進行同步而不是隱式鎖定(this)。這種情況包括:

  • 您希望在不使用this的情況下同步對基元的訪問。您只能在Object上同步,因爲每個Object都與Java中的隱式監視器關聯。基元沒有這樣的隱式監視器,因此你需要使用一個鎖對象。使用包裝類是一個可憐的和不正確的選擇,特別是如果你最終modifying the lock object in the guarded block
  • 您想要在實際保護關鍵部分的對象上進行同步,當在this上進行同步時不能保證線程安全。例如,如果您正在同步對類A的實例共享的ArrayList實例的訪問,那麼同步A的實例將毫無用處。一個線程可能創建一個A的新實例並獲得對列表的訪問權限,而另一個線程正在修改它。如果你使用不同的鎖,所有線程都必須爭奪,那麼你可以保護列表;這個鎖可能是與A.class相關的鎖,但它可以是任何可以提供相同保證的對象。
  • 您想執行鎖定分割以確保不同的保護塊受不同的鎖而不是相同的鎖保護。換句話說,如果線程安全以允許不同的線程獲取不同的鎖來訪問不同的關鍵部分,那麼您可以爲每個關鍵部分設置不同的鎖。

下面是拆鎖使用的例子:

private Object method1Lock = new Object(); 
private Object method2Lock = new Object(); 

public void method1(){ 
    synchronized(method1Lock){ 
     .... 
    } 
} 

public void method2(){ 
    synchronized(method2Lock){ 
     .... 
    } 
} 

你會使用分裂鎖時,你可以確保method1method2併發執行不違反類不變。這樣,您可以提高需要訪問同一對象的線程的性能,但會調用不同的方法。


在您的其他問題,

例如,在第二個例子中,將線程仍然可以執行synchronized塊中的代碼,因爲鎖是不相關的「這個」實例?

在第二個示例中,任何進入保護區域的線程都必須獲取與aStringBufferObject關聯的鎖定。如果另一個線程持有該鎖,則當前線程將不會繼續進行。當您指定this時,線程必須獲取與當前對象關聯的鎖。在這兩種情況下,線程都必須獲得一個鎖;這些示例僅在用作鎖的對象中有所不同。

2

在一個對象上同步意味着在同一對象上同步的其他塊將不得不等待。例如:

public void methodA() { 
    synchronized(obj) { 
     //Do one job 
    } 
} 

public void methodB() { 
    synchronized(obj) { 
     //Do another job 
    } 
} 

如果你在一個線程中調用methodA(),然後調用methodB()在另一個線程,methodB()不會前methodA()完成完成。

2

​​塊是一個監視器,它省略了細節以鎖定和解鎖互斥鎖。由於Java中的每個對象都有內部鎖(請參閱源代碼Object類),因此在使用​​語句時,JVM將幫助您同步關鍵部分。您也可以使用包java.util.concurrent.locks中的ReentrantLock同步塊。