今天面試官問了乙個問題,如果在乙個類中的普通方法加上synchronized 關鍵字,兩個執行緒可以同步方法這個方法嗎?為什麼
當時回答是不可以同步,然後面試官確認我說一定嗎?當時就知道回答錯了。
現在實現了下,原來是類鎖和物件鎖的區別所在,也算是普及了下相關知識吧。
類鎖:就是在方法前面加上 static synchronized或者方法裡面 synchronized(mainthings.class) 這兩個寫法,那麼這是乙個類鎖。
物件鎖:就是在方法前面加上synchronized或者方法裡面 synchronized(this) 這兩個寫法,那麼這是乙個類鎖。
結論:如果是物件鎖的話,兩個執行緒可以同時訪問同乙個方法。
如果是類鎖的話,兩個執行緒是不可以同時訪問同乙個方法,當前執行緒會將另外乙個執行緒阻塞起來,等當前執行緒處理完了釋放了當前鎖後才可以進來。
原因:物件鎖-》面對每乙個物件來說,都有各自的鎖,每個執行緒訪問不同物件時都可以擁有自己的鎖,所以不會造成這個執行緒的物件被另乙個物件上鎖。
類鎖-》對每個執行緒來說,只有一把鎖,誰先擁有這把鎖,誰先訪問,其他執行緒阻塞,等當前訪問完了的執行緒釋放鎖後,其他執行緒才可以訪問。
public class dothing1 implements runnable
@override
public void run()
public class dothing2 implements runnable
@override
public void run()
public class dothing2 implements runnable
@override
public void run()
主類:public class mainthings
/*** @param args
*/public static void main(string args)
/**
* @param args
*/public static void main(string args) {
// todo auto-generated method stub
mainthings mainthings=new mainthings();
mainthings mainthings2=new mainthings();
dothing1 do1=new dothing1(mainthings);
dothing2 do2=new dothing2(mainthings2);
thread t1=new thread(do1);
thread t2=new thread(do2);
t1.start();
t2.start();
執行結果:
thread-0 dothing1 is begin
this isthread-0 entry
this isthread-0 out
thread-1 dothing2 is begin
this isthread-1 entry
this isthread-1 out
假設方法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。
另一種情況:假設現在有兩個test類
test t1=new test();
test t2=new test();
t1.methodb();//此時當前執行緒持有了t1物件的鎖
t2.methodb();//此時當前執行緒也持有了t2物件的鎖
當前執行緒持有了兩把鎖,鎖的物件分別是兩個不同的test類的例項t1和t2,互相沒有影響。
再一種情況:假設在多執行緒環境下,兩個執行緒都可以訪問test t=new test();
此時假設thread1裡呼叫t.methodb();同時thread2裡呼叫t.methodb()
這時假設thread1先搶到t物件的鎖,那麼thread2需要等待thread1釋放t物件的鎖才可以執行b方法。
結果像這樣:
thread1獲得t的鎖--thread1執行methodb--thread1執行methoda--釋放t的鎖---thread2獲得t的鎖--thread2執行methodb--thread2執行methoda--釋放t的鎖。
synchronized還有很多種使用方法,但只有明白是那條執行緒獲得哪個物件的鎖,就很容易明白了
Java多執行緒 類鎖和物件鎖
我們設想某個執行緒獨佔某個類,必須執行完才能再次建立物件 預期輸出以下結果 物件鎖示例 關鍵字synchronized取得的鎖都是物件鎖,而不是把一段 方法 當做鎖,所以 中哪個執行緒先執行synchronized關鍵字的方法,哪個執行緒就持有該方法所屬物件的鎖 lock 在靜態方法上加synchr...
多執行緒的補充 關於類鎖和物件鎖的理解
鎖什麼時候需要使用?概述 每個類建立的物件都對應一把鎖,如果是多個執行緒訪問不同物件的時候,其它執行緒不用等待鎖的釋放,因為它們是不同的鎖。請看 public class test class mythread implements runnable 重寫run方法 public void run ...
多執行緒 互斥物件和鎖
互斥物件的主要操作有兩個,即加鎖 lock 和解鎖 unlock 當乙個執行緒對互斥物件進行lock操作並成功獲得這個互斥物件的所有權,在此執行緒對此物件unlock前,其他執行緒對這個互斥物件的lock操作都會被阻塞。有些傾向需要對多個互斥物件進行加鎖,考慮下面的 std mutex mt1,mt...