2021-0203 執行緒同步和synchronized
阿新 • • 發佈:2021-02-13
執行緒同步和synchronized
背景舉例(銀行取錢)
假如賬戶中有400元,用銀行卡和存摺同時去取錢會不會取出800元?
public static void main(String[]args) {
Money m=new Money();
new Thread(m).start();
new Thread(m).start();
}
int count=400;
public void run() {
System.out.println("餘額還有" +count);
if(count==400) {
System.out.println(Thread.currentThread().getName()+"準備取錢");
count=0;
System.out.println(Thread.currentThread().getName()+"取錢成功");
}else{
System.out.println(Thread.currentThread().getName()+"取錢失敗");
}
按照如圖程式碼執行出現了以下結果:
說明取到了800元。
原因分析
兩個執行緒啟動時,在一個執行到count=0之前,另一個也進入到判斷中,這樣由於兩個執行緒幾乎同步,有機率都進入判斷中,所以取錢了兩次(即在一次訪問扣款前,另一個也訪問進去的情況。)
synchronized
Java語言的關鍵字,當它用來修飾一個方法或者一個程式碼塊的時候,能夠保證在同一時刻最多隻有一個執行緒執行該段程式碼。
一、當兩個併發執行緒訪問同一個物件object中的這個synchronized(this)同步程式碼塊時,一個時間內只能有一個執行緒得到執行。另一個執行緒必須等待當前執行緒執行完這個程式碼塊以後才能執行該程式碼塊。
二、然而,當一個執行緒訪問object的一個synchronized(this)同步程式碼塊時,另一個執行緒仍然可以訪問該object中的非synchronized(this)同步程式碼塊。
所以當用synchronized將判斷修飾後將只能取出400元,但注意的是,不能確定是哪個執行緒取出的。