2013-08-01 16 views
0

我想知道兩個方案在多線程環境中是否等價。內在和外在全局鎖定的Java等價

private final Lock globalLock = new ReentrantLock(); 

方案1

public void addListener(Listener listener) { 
    globalLock.lock(); 
    try{ 
    //blah blah 
    }finally { 
     globalLock.unlock(); 
    } 
} 

public void removeListener(Listener listener) { 
    globalLock.lock(); 
    try{ 
    //blah blah 
    }finally { 
     globalLock.unlock(); 
    } 
} 

方案2

public synchronized addListener(Listener listener) { 
} 

public synchronized removeListener(Listener listener) { 
} 

我認爲第一種情形在多線程環境中的競爭條件,因爲如果線程A調用addListener()方法以前主題B調用removeListener(),即使線程A invo,線程B仍然可能在線程A之前獲取鎖線程B調用removeListener()之前的ked addListener()。這個假設是否正確,或者Java保證在線程調度之前至少執行一個方法的語句。

+0

是,globalLock是一個全球性的最終場 –

+0

您所描述的情況是不是競爭狀態。調用addListener和removeListener不能從「之前」或「之後」的角度考慮。 –

回答

1

它們是功能上等同的(假設globalLock是最終實例變量)。

在你的第一個例子,如果兩個線程同時調用這兩種方法中,只有其中一人將能夠獲得鎖,第二個將不得不等待,直到第一個釋放鎖。

+0

是的,我明白這一點。我的問題是,如果兩個線程獨立調用方法,但線程A在線程B之前調用,線程B是否可以在線程A之前獲得鎖定?有效地,我想知道是否給addlistener()在獨立線程之前調用removeListener(),這個實現提供了Program Order的保證嗎? –

+0

不知道我是否理解:要麼使用同步來確保線程A在線程B之前調用該方法,那將會發生什麼或者不會發生,它將是隨機的。這同樣適用於同步方法。 – assylias

1

目前還不清楚全局鎖是什麼。如果它是一個實例字段

private final Lock globalLock = new ReentrantLock(); 

public void addListener(Listener listener) { 
    globalLock.lock(); 
    ... 

那麼答案是肯定的,這兩個方案是等價的

+0

請看我對assylias的評論 –

0

他們在多線程環境完全等同。 在功能上它們與assylias建議的相同。

但是他們在這兩種方法中差異很大。 最大的區別在於,在場景1中,您的鎖是私人的。 ,因此它是一個很好的做法,因爲你確定沒有其他人可以擁有你的鎖。 雖然場景是不是一個很好的方法(除了在某些情況下),因爲 任何其他用戶可以持有鎖不再像現在您鎖是公共

所以功能上等同,但設計它們是不同的。