2011-05-27 96 views
4

如果我有以下代碼同步方法VS同步塊

class SomeClass {  
... 
public synchronized methodA() { 
.... 
} 

public synchronized methodB(){ 
.... 
} 
} 

這將同步的「這個」物體上。但是,如果我的主要目的是確保多個線程同時不使用methodA(或methodB),但它們可以同時使用methodA和methodB,那麼這種設計是否會受到限制?因爲此處thread1鎖定運行methodA的對象(與對象關聯的監視對象),但同時thread2也等待對象鎖定,即使methodA和methodB可同時運行。
這種理解是否正確?

如果是,是這種情況下,我們在一個私人虛擬對象上使用同步塊,以便methodA和methodB可以與不同線程並行運行,但不能與不同線程的methodA(或methodB)運行。
謝謝。

+0

在這裏找到答案:http://stackoverflow.com/questions/574240/synchronized-block-vs-synchronized-method - 請使用搜索功能,其他的問題,甚至有完全相同的名稱,涵蓋了同樣的問題。 – 2011-05-27 09:59:45

+0

我認爲你是對的,但一個問題是,對於靜態方法的鎖定與普通對象方法的鎖定不同。該文檔是相當不錯的這個東西:http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html – 2011-05-27 10:01:23

回答

9

你已經回答了自己的問題:每使用一個方法鎖定對象,你是安全的。

private final Object lockA = new Object(); 
private final Object lockB = new Object(); 
public void methodA() { 
    synchronized(lockA){ 
     .... 
    } 
} 
public void methodB() { 
    synchronized(lockB){ 
     .... 
    } 
} 

對於更高級的鎖定機構(例如ReentrantLock),由Brian Goetz等人讀Java Concurrency in Practice。您還應該閱讀Effective Java by Josh Bloch,它也包含一些關於使用​​的項目。

+1

,使'lockA'和'lockB'爲'final'領域。 – 2011-05-27 10:00:26

+0

@John是的,真的,馬虎。 – 2011-05-27 10:03:11

2

如果您想允許同時運行methodA()methodB(),但另外將每個方法限制爲一個線程,則需要兩個單獨的對象進行同步。例如:

class SomeClass { 
    private final Object lockA = new Object(); 
    private final Object lockB = new Object(); 

    public void methodA() { 
     synchronized (lockA) { 
      // 
     } 
    } 

    public void methodB() { 
     synchronized (lockB) { 
      // 
     } 
    } 
} 
1

如果我的理解是正確的,你要允許線程T1在同一時間線程T2運行的methodB()運行了methodA() - 但你不希望線程T1運行了methodA( )同時線程T2運行methodA()(和methodB相同)對嗎? 對於這種情況,你不能僅僅簡單的使用synchronized方法 - 而不是像你說的,你將需要2個虛擬物件(一個爲methodA,一個用於的methodB)同步上。或者你可以使用新的Lock類 - 每個方法一個Lock實例。

+0

是的,這正是我的意思 – Ankur 2011-05-27 10:10:12

+0

然後你就可以使用上面所示的方法中的一種或正如我所說看看java.util.concurrent.locks.ReentrantLock中的實例。 – Liv 2011-05-27 10:27:32