2012-08-16 22 views
0

可能重複:
synchronized block vs synchronized method?同步(這)阻止整個對象?

從接受這個問題的答案:In Java critical sections, what should I synchronize on? 我得知

public synchronized void foo() { 
    // do something thread-safe 
} 

和:

public void foo() { 
    synchronized (this) { 
     // do something thread-safe 
    } 
} 

做的事情完全一樣。但在第一種情況下,我們只使同步對象的一種方法,而在第二種情況下,我們使不可訪問的整個對象。那麼爲什麼這兩個代碼片段做同樣的事情呢?

+0

http://stackoverflow.com/questions/1149928/what-is-the-difference-between-a-synchronized-method-and-synchronized-block-in-j?rq=1,http:// stackoverflow.com/questions/10185867/java-synchronized-difference-threading?rq=1,http://stackoverflow.com/questions/8519700/what-is-the-difference-between-a-synchronized-function-and-同步塊 – 2012-08-16 05:50:49

回答

4

你似乎在混合的東西。

首先

public synchronized void method() { 
} 

是等價的,從同步的角度來看,以:

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

的優點/缺點已經提到和各種重複提供更多的信息。

其次,

synchronized(someObject) { 
    //some instructions 
} 

意味着,在同步塊中的指令不能同時由2個線程,因爲他們需要獲取關於someObject監視器這樣做執行。 (假設someObject是最後一個不會改變的參考)。

就你而言,someObject恰好是this

即使this上的顯示器由線程保存,因爲它正在運行同步塊,您的對象中任何未同步的代碼仍可以同時執行。換句話說,synchronized(this)不會「鎖定整個對象」。它只能阻止2個線程同時執行同步塊。

最後,如果有兩個​​方法(用this作爲鎖兩者),如果一個線程(T1)獲取關於this鎖來執行的那些2種方法中的一種,沒有其他的線程被允許執行任何這兩種方法,因爲他們需要獲得已經由T1持有的this上的鎖。

這種情況可以創建在臨界區,在這種情況下,更細粒度的鎖定策略必須被使用(例如,使用多個鎖)的爭用。

+0

謝謝,你解釋我所不知道的一切。但我不明白爲什麼我需要鎖定final(不可更改)對象?:'假設someObject是最終的引用不會改變'。什麼是監視器?這是什麼意思?在「Object」類的源代碼中,我沒有發現與監視器有關的任何信息。這是一個標誌,作爲「布爾」?再次感謝。 – MyTitle 2012-08-16 16:15:59

+0

這是很多問題! (1)最後:如果你使用'同步(someObjectThatIsNotFinal)'和地方在你的代碼,你有'someObjectThatIsNotFinal =新的對象();',接到了接下來的線程將鎖定不同的對象,並可能進入,而另一個synchronized塊線程仍在那裏。 (2)[監視器在JLS定義](http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.1)。它是如何實現的取決於JVM,並且它本身沒有任何引用監視器的Object類。 – assylias 2012-08-16 16:24:30

+0

非常感謝,非常好的解釋:) – MyTitle 2012-08-16 16:33:38

0

他們不做同樣的事情。第一部分從頭到尾同步。其次是同步塊(不是全部方法)。其次有一些靈活性。

+2

但在這種情況下,synchronized塊覆蓋*整個*方法..(或者無論如何,整個「做某件事」部分)。 – 2012-08-16 05:52:54

+0

hmm。但是我們說我們想鎖定WHOLE對象,直到關鍵代碼沒有執行,因爲我們傳遞參數this''這個對象。所以我認爲,當在同步塊中使用'this'時,我們鎖定所有對象。但是,當我們使用私有引用而不是'this'時,我們只鎖定同步塊。 – MyTitle 2012-08-16 05:55:22

1

我們不同步對象,而是同步一段代碼。在第一個代碼塊是方法本身,而第二個代碼塊是​​塊。

該對象只提供鎖以防止多個線程同時進入該代碼塊。在第一種情況下,this對象(在其上調用該方法的對象)將隱式用作鎖,而在第二種情況下,它不一定是this對象,它也可以是其他對象。

+0

好吧,我認爲當使用'this'作爲參數時,我們鎖定了WHOOLE對象。但是,現在誕生了另外一個問題...'同步(這)'意味着'Thread1'可以獲取對象的監視器,所以''直到釋放Thread1'它Thread2'不能訪問臨界區。但是如果我們在課堂上有幾個關鍵部分,我們通過'this'作爲參數(我認爲每個對象只有一個顯示器,不再有)?例如線程1進入臨界區,並獲得對象的監視器,在同一時間線程2要執行* *另一個關鍵部分,但它看到該對象的(這個)顯示器沒有公佈。 – MyTitle 2012-08-16 07:03:40

+0

@MyTitle對於評論來說太長了 - 請參閱我的回答。 – assylias 2012-08-16 11:25:25

1

他們做同樣的事情。第一種形式是第二種形式的短手形式。兩個構建體之間

一個微小的差別是這樣的 - 同步塊被編譯成monitorenter(操作碼0xC2)和monitorexit(操作碼0xC3)指令。 同步方法在編譯時在運行時常量池中被 ACC_SYNCHRONIZED標誌區分,該標誌由JVM的方法調用指令檢查。儘管如此,這種差異在實踐中並沒有多大意義。