天天看點

Java面試題1:synchronized方法調用

1 synchronized同步方法調用另一個synchronized同步方法

public synchronized void methodA(int a, int b) {
};

public synchronized void methodB(int a){
    methodA(a, 0);
}      

答:

要明白兩個問題,①鎖的對象是誰;②誰持有了鎖。

有三種情況:

(1)假設方法A和B是在同一個類Test中的兩個方法。

Test t = new Test(); 
t.methodB();      

這個時候,methodB方法被調用時,因為加了synchronized ,需要先獲得一個鎖,這個鎖的對象應該是t,也就是目前的這個Test類的執行個體,而獲得鎖的東西是線程,也就是說目前線程拿到了t的鎖(而不是B方法獲得鎖),這個時候B方法内調用methodA,因為A也加了synchronized,也需要獲得一個鎖,因為A和B都是Test類中的方法,是以目前線程要獲得的鎖的對象也是t。由于目前線程在執行B方法時已經持有了t對象的鎖,是以這時候調用methodA是沒有任何影響的,相當于方法A上沒有加synchronized。

加在非static方法上的synchronized方法是和synchronized(this)塊等價的,均為對象鎖,即對this加鎖。獲得目前對象鎖的線程,可以繼續獲得目前對象鎖,JVM負責跟蹤對象被加鎖的次數。線程運作B方法,此時如果this鎖可以用,線程獲得該鎖,線程給對象加鎖,計數器變成1,然後B方法調用A方法,由于是對同一個對象同一個線程,線程可以繼續獲得鎖,計數器變為2,表示this被加鎖2次。A方法完畢後,線程釋放鎖,計數器變為1,此時對象鎖對其他線程依然是不可獲得的。B方法完畢後,線程繼續釋放鎖,此時計數器變為0,表示鎖被完全釋放,其他線程可以獲得對象鎖。

(2)假設現在有兩個Test類

Test t1 = new Test(); 
Test t2 = new Test(); 
t1.methodB(); //此時目前線程持有了t1對象的鎖
t2.methodB(); //此時目前線程也持有了t2對象的鎖      

目前線程持有了兩把鎖,鎖的對象分别是兩個不同的Test類的執行個體t1和t2,互相沒有影響。