前言併發
最近被問到了這個問題,第一次回答的也是很很差,在此參考網上答案進行整理記錄。供你們學習參考。學習
Synchronized修飾非靜態方法spa
Synchronized修飾非靜態方法,其實是對調用該方法的對象加鎖,俗稱「對象鎖」。線程
Java中每一個對象都有一個鎖,而且是惟一的。假設分配的一個對象空間,裏面有多個方法,至關於空間裏面有多個小房間,若是咱們把全部的小房間都加鎖,由於這個對象只有一把鑰匙,所以同一時間只能有一我的打開一個小房間,而後用完了還回去,再由JVM 去分配下一個得到鑰匙的人。code
狀況1:同一個對象在兩個線程中分別訪問該對象的兩個同步方法對象
結果:會產生互斥。blog
解釋:由於鎖針對的是對象,當對象調用一個synchronized方法時,其餘同步方法須要等待其執行結束並釋放鎖後才能執行。正如上面所解釋的,至關於一個對象只有一把鑰匙了,裏面的兩個同步方法是兩個房間,所以,同一時間只能用一個鑰匙訪問一個方法。同步
狀況2:不一樣對象在兩個線程中調用同一個同步方法class
結果:不會產生互斥。方法
解釋:由於是兩個對象,就至關於兩個大房子,彼此之間互不干擾,具備兩把鑰匙。鎖針對的是對象,並非方法,因此能夠併發執行,不會互斥。形象的來講就是由於咱們每一個線程在調用方法的時候都是new 一個對象,那麼就會出現兩個空間,兩把鑰匙。
Synchronized修飾靜態方法
Synchronized修飾靜態方法,其實是對該類對象加鎖,俗稱「類鎖」。
狀況1:用類直接在兩個線程中調用兩個不一樣的同步方法
結果:會產生互斥。
解釋:由於對靜態對象加鎖實際上對類(.class)加鎖,類對象只有一個,能夠理解爲任什麼時候候都只有一個空間,裏面有N個房間,一把鎖,所以房間(同步方法)之間必定是互斥的。
注:上述狀況和用單例模式聲明一個對象來調用非靜態方法的狀況是同樣的,由於永遠就只有這一個對象。因此訪問同步方法之間必定是互斥的。
狀況2:用一個類的靜態對象在兩個線程中調用靜態方法或非靜態方法
結果:會產生互斥。
解釋:由於是一個對象調用,同上。都調用靜態方法的時候,至關因而同一個類鎖,用的都是同一個類對象。
都調用非靜態方法的時候,至關因而同一個對象鎖。
狀況3:一個對象在兩個線程中分別調用一個靜態同步方法和一個非靜態同步方法
結果:不會產生互斥。
解釋:由於雖然是一個對象調用,可是兩個方法的鎖類型不一樣,調用的靜態方法其實是類對象在調用,即這兩個方法產生的並非同一個對象鎖,所以不會互斥,會併發執行。
例子
pulbic class Something(){ public synchronized void isSyncA(){} public synchronized void isSyncB(){} public static synchronized void cSyncA(){} public static synchronized void cSyncB(){} }
那麼,加入有Something類的兩個實例a與b,那麼下列哪組方法能夠被1個以上線程同時訪問呢?
a. x.isSyncA()與 x.isSyncB()
b. x.isSyncA()與 y.isSyncA()
c. x.cSyncA()與 y.cSyncB()
d. x.isSyncA()與 Something.cSyncA()
這裏,很清楚的能夠判斷:
a,都是對同一個實例的synchronized域訪問,所以不能被同時訪問
b,是針對不一樣實例的,所以能夠同時被訪問
c,由於是static synchronized,因此不一樣實例之間不會被限制
d,書上的答案是能夠被同時訪問的,答案理由是synchronzied的是實例方法與synchronzied的類方法因爲鎖定(lock)不一樣的緣由。