來看下面這個程式
/*需求:
銀行有一金庫。有兩個儲戶分別存300元,每次存100,存3次。
目的:該程式是否有安全問題。如果有,如何解決?
*/
class bank
}class cus implements runnable }}
class bankdemo
}
執行結果可能為:
如何找問題:
1.明確哪些**是多執行緒執行**
2.明確共享資料
3.明確多執行緒執行**中哪些語句是操作共享資料的
在上面的執行程式中,
run方法和add方法是多執行緒執行**
b和sum是共享資料
操作b的是b.add(100); 操作sum的是sum = sum + n;和system.out.println("sum = "+sum);
先用同步**塊封裝**
class bank
catch(exception e){}
system.out.println("sum = "+sum);
} }}class cus implements runnable }}
class bankdemo
}
函式和同步**塊都可以封裝**,唯一的區別是同步**塊具備同步的特性。
為了讓函式具備同步性。把
synchronized關鍵字作為修飾符放到函式上
class test implements runnable
catch(exception e){}
system.out.println(thread.currentthread().getname()+" tick = "+tick--);
}//}
} }}class ticketdemo
}
執行結果:
可以看到程式中只有thread-0執行了。這是因為當乙個執行緒搶到執行權進入run方法後,就把狀態改為已鎖狀態,其他執行緒無法進入。
解決方法:將需要同步的**封裝成函式
class test implements runnable
} public synchronized void show()
catch(exception e){}
system.out.println(thread.currentthread().getname()+" tick = "+tick--);
} }}class ticketdemo
}
同步函式用的是哪乙個鎖呢?
函式需要被物件呼叫。那麼函式都有乙個所屬物件引用,就是this。
所以同步函式的鎖是this
通過買票程式來驗證
使用兩個執行緒來買票,乙個執行緒在同步**塊中,乙個執行緒在同步函式中,都在執行買票動作。若同步不會出現錯誤的票。
class test implements runnable
catch(exception e){}
system.out.println(thread.currentthread().getname()+" tick = "+tick--);}}
}} else
while(true)
show();
} public synchronized void show()
catch(exception e){}
system.out.println(thread.currentthread().getname()+" show... "+tick--);
} }}class ticketdemo1
catch(exception e){}
t.flag = false;
t2.start();}}
輸出結果中有-1號票,說明這個程式是不安全的。
已經使用了同步還出現錯誤。這時要考慮同步的兩個前提條件:
1.必須有兩個或兩個以上的執行緒
2.必須使用同一把鎖。
通過分析,同步**塊中的鎖是obj,而同步函式中的鎖不是。把鎖都換成this
class test implements runnable
catch(exception e){}
system.out.println(thread.currentthread().getname()+" tick = "+tick--);}}
}} else
while(true)
show();
} public synchronized void show()
catch(exception e){}
system.out.println(thread.currentthread().getname()+" show... "+tick--);
} }}class ticketdemo1
catch(exception e){}
t.flag = false;
t2.start();}}
輸出結果正確,說明同步函式的鎖是this。
如果同步函式被靜態修飾後,使用的鎖是什麼?
通過驗證,發現不再是this
,因為靜態方法中不可以定義
this。
靜態進記憶體時,記憶體中沒有本類物件,但是一定有該類對應的位元組碼檔案物件 類名.class
該物件的型別是
class
靜態的同步方法使用的鎖是該方法所在類的位元組碼檔案 類名.class.
多執行緒靜態同步函式
多執行緒靜態同步函式和非靜態同步函式的區別是啥?靜態同步函式 就是方法使用了static關鍵字修飾 非靜態同步函式 沒有用static關鍵字修飾的方法,也就是使用this鎖的同步函式 那麼靜態同步函式使用的啥鎖呢?分析 兩個執行緒,乙個執行緒使用靜態同步函式,乙個使用同步 塊this鎖,如果執行緒不...
多執行緒同步
synchronized 物件 其中物件相當於乙個標誌 鎖 用於判斷 同步 塊 同步的前提必須是兩個或兩個以上的執行緒,且共用同乙個鎖 同步解決了多執行緒的安全問題 弊端 多執行緒需要判斷鎖,消耗了資源 同步函式 將synchronized放在函式名前面即可 即具有同步性質 使用的鎖是this 靜態...
多執行緒同步
同步 即限制某個資源在同一時間只能被同乙個執行緒訪問。執行緒安全問題 多個執行緒共同處理共享資源所導致的。解決 多執行緒處理乙個共享資源時,將處理共享資源的 利用關鍵字synchronized修飾。同步 塊 synchronized修飾 塊,synchronized lock 同步方法 synchr...