2012-09-14 88 views
1

有任何兩者之間的區別:「同步函數」和「函數內部的同步塊」之間是否存在任何功能差異?

public void synchronized func() { 
} 

public void func() { 
    synchronized(this) { 
    } 
} 

我在全功能func是同步的第一種情況和第二種情況下只能理解函數的代碼的一部分同步。但它有所作爲嗎?我的意思是說明總是一個接一個地執行。如果線程在到達同步塊時無法獲取鎖,它將不會在同步塊之後啓動操作!

是否有任何功能差異,或者這只是一個很好的做法?

+0

是否會強制函數上的任何擴展類的「​​同步」? –

+0

@MichaelLaffargue:它真的這麼做嗎?是同步繼承? – Thilo

+0

如果你在這裏問這個問題,你可以使用+1 ...... – Thilo

回答

0

從鎖定角度來看沒有區別。

從字節碼的角度來看,可以告訴第一種方法是使用反射或大多數類的查看器同步的。第二種情況很難確定是這種情況。

如果您想要隱藏所使用的鎖,即您沒有使用this,因此呼叫者不能混淆事件,則首選使用塊同步。

4

在第二種情況下,只有一部分函數的代碼被同步。但它有所作爲嗎?

是的,如果在同步零件外有很多代碼,它確實會有所幫助。

public void func() { 
    someHeavyOperations(); 
    synchronized(this) { 
     criticalSectionOperations(); 
    } 
    someMoreHeavyOperations(); 
} 

你想保持你的關鍵部分儘可能小。

如果線程在到達同步塊時無法獲取鎖,它將不會在同步塊之後啓動操作!

不,但它能夠在同步塊之前完成操作,並且它不會讓任何人在等待同步塊之後等待操作。

即使在同步塊外沒有更多代碼,該構造也很有用,因爲您可以在除this之外的其他內容上同步,例如對keep the lock private or more granular

+0

你能解釋一下這一點嗎?「即使沒有更多的代碼在synchronized塊之外,這個構造也是有用的,因爲你可以在其他事情上進行同步,例如保持鎖私人或更細粒度。「_我不明白 – saplingPro

+0

檢查鏈接,或@布賴恩的答案。能夠選擇其他鎖對象非常有用。 – Thilo

+0

+1我希望他們在大學教授這個最小鎖定範圍的概念做得更好。我在面試中問同樣的問題,你會驚訝有多少人只是不明白:) – Brady

2

我不認爲在上面有任何實際的區別。

但是,我會偏好後者,因爲它更靈活。您可以鎖定特定的鎖對象,而不是鎖定包含對象(this),而不同的方法可以指定不同的鎖對象(取決於同步要求)。這意味着您可以調整同步,使其在您需要時更加細化。

例如

public synchronized void doSomething() { 
    ... 
} 

(上this鎖)

public void doSomething() { 
    synchronized(someLockObject) { 
     ... 
    } 
} 
+0

我是不是在這兩種情況下鎖定'this'? – saplingPro

+0

不,你可以用第二個版本同步(somethingElse)。 – Thilo

+0

你是。我的觀點是,在第二種情況下,你不必這樣做。你可以指定一個特定的鎖對象,如果你的線程模型允許的話,可能會有很多 –

0

你需要保持Critical Section as small as possible. so synchronized(this) is more useful

但是如果你的關鍵部分是你的方法那麼你可以繼續申報方法爲​​

從1.5開始,你可以隨時使用ReentrantLock

折返互斥鎖具有相同的基本行爲和語義的隱式監視器鎖使用synchronized方法和語句所訪問,但功能更強大。

class X { 
private final ReentrantLock lock = new ReentrantLock(); 
// ... 

public void m() { 
    lock.lock(); // block until condition holds 
    try { 
    // ... method body 
    } finally { 
    lock.unlock() 
    } 
} 
} 
0

如果你同步方法的全部內容則沒有功能上的差異。如果你只是同步部分方法,那麼同步化的範圍是不同的。

你是正確的,同步塊之後的代碼將不會在同步塊之前執行。然而,線程可以在任何不同步的點上換出。考慮以下幾點:

synchronized (this) { 
    //sycnronized bit 
} 
// some other code 

如果有兩個線程,A & B和A獲得鎖乙將阻塞,直到甲退出同步塊。但是A退出該塊後可以立即換出。 B可以在A被換回之前進入同步塊並且完成該功能。

這可以被非常普遍地使用,例如,以確保可變實例變量對於計算範圍是一致的,同時允許多個線程執行昂貴的計算。例如。

Object localCopy; 
synchronized (this) { 
    localCopy = this.instanceVar; 
} 
// expensive calculation using localCopy which won't change even if instanceVar is changed.