synchronized可以對類或者物件加鎖,從而保證多個執行緒在同乙個時刻只有乙個執行緒執行被synchronized修飾的**。
例子(簡單的購票**):
現在設計乙個普通的購票場景,乙個票務處,五個客戶同時在票務處買票:
1).票務處(ticketmanager):
/**
* 票務處類
* @classname: ticketmanager
* @description: 票務處類
* @author: vincentho
* @date: 2023年3月30日 下午12:38:36
*/public
class
ticketmanager
public
ticketmanager
(int ticketnum)
}
2).購票客戶(buyticketclient)
/**
* 購票客戶
* @classname: buyticketclient
* @description: 購票客戶
* @author: vincentho
* @date: 2023年3月30日 下午12:39:40
*/public
class
buyticketclient
extends
thread
@override
public
void
run(
)}
3).測試主類(buyticketmain)
/**
* 主類
* @classname: buyticketmain
* @description: 主類
* @author: vincentho
* @date: 2023年3月30日 下午12:41:30
*/public
class
buyticketmain
}}
結果:
thread-0得到票,餘票:2
thread-4得到票,餘票:0
thread-3得到票,餘票:1
thread-2得到票,餘票:2
thread-1得到票,餘票:2
如上所示,這結果很明顯不是我們想看到的。五個人同時買票,餘票應該從5到0,而不應該這樣混亂。這就是因為五個執行緒,同時操作乙個資源導致的後果,那麼下面如果在buyticket()方法中加入synchronized鎖,再看看結果如何:
/**
* 票務處類
* @classname: ticketmanager
* @description: 票務處類
* @author: vincentho
* @date: 2023年3月30日 下午12:38:36
*/public
class
ticketmanager
}public
ticketmanager
(int ticketnum)
}
結果:
thread-0得到票,餘票:4
thread-4得到票,餘票:3
thread-3得到票,餘票:2
thread-2得到票,餘票:1
thread-1得到票,餘票:0
如上所示,得出了我們想要的結果,這就是synchronized鎖的作用
如果synchronized不是鎖在靜態方法上,那麼都是屬於物件鎖。物件鎖鎖住的是物件,只要是屬於同乙個物件,那麼多個執行緒是不能同時進行的(像上面的購票例子就是物件鎖)
例子:
public
class
instancesync
catch
(exception e)
}}
public
class
instancesynctest
@override
public
void
run()}
public
static
void
main
(string[
] args)
}
執行結果:
thread-1------執行開始
thread-0------執行開始
執行物件鎖方法。。。
執行物件鎖方法。。。
thread-0------執行結束
thread-1------執行結束
從結果可以看出,兩個執行緒是同步進行的。那麼假如操作的是同乙個物件,結果會如何呢,下面改一下測試類的**:
public
class
instancesynctest
@override
public
void
run()}
public
static
void
main
(string[
] args)
}
結果:
thread-0------執行開始
thread-1------執行開始
執行物件鎖方法。。。
thread-0------執行結束
執行物件鎖方法。。。
thread-1------執行結束
建立執行緒物件的時候如果傳入同乙個物件,兩個執行緒操作同乙個物件,那麼執行緒就不能同時執行了。這就是因為synchronized在這裡是對物件上鎖,所以只要是不同的物件,就不會被鎖住。
延申:如果說這是鎖住乙個物件的,那麼假如乙個類有多個sychronized修飾的方法,那麼結果會怎麼樣呢?改一下上面的方法:
public
class
instancesync
catch
(exception e)
}public
synchronized
void
other()
catch
(exception e)
}}
public
class
instancesynctest
@override
public
void
run()}
class
testthread2
extends
thread
@override
public
void
run()}
public
static
void
main
(string[
] args)
}
注意上面的例子是開啟了兩個執行緒,分別呼叫了同乙個物件的兩個有synchronized的方法,那麼結果是:
thread-0------執行開始
thread-1------執行開始
執行物件鎖方法。。。
thread-0------執行結束
rbq rbq。。。
thread-1------執行結束
結果就是執行緒阻塞呼叫方法,和多執行緒呼叫同乙個物件同乙個方法是乙個結果。這就是物件鎖的作用。
synchronized如果在static方法上,那麼這個synchronized的範圍就是這個類,也就是類鎖,它鎖的是這個類的class物件。而在jvm中,class物件是放在永久代(元空間)中的,所以class物件是唯一的,所以多少個執行緒,操作這個類多少個物件,呼叫這個方法的時候都是會被阻塞的。
**注意:**如果乙個類裡面,類鎖和物件鎖同時都有,兩個執行緒分別呼叫這個類鎖的方法和物件鎖的方法,也是可以同時執行的,因為分別所的是類的class物件和例項物件
Java的高併發程式設計系列(三)
鎖定某物件o,如果o的屬性發生改變,不影響鎖的使用,但是如果o變成另外乙個物件,則鎖定的物件發生改變,應該避免將鎖定物件的引用變成另外乙個物件。public class demo17 catch interruptedexception e system.out.println thread.cur...
併發程式設計(三)
不可變物件只要發布了,一定是執行緒安全的。滿足什麼條件是不可變物件?如何建立乙個不可變物件?public static mapunmodifiablemap map extends k,extends v m serial include private static class unmodifia...
Java併發程式設計系列 CountDownLatch
countdownlatch簡介 countdownlatch是基於aqs實現的乙個執行緒同步工具,也稱為閉鎖。它的作用是讓乙個或者多個執行緒等待某個事件的發生。簡單的理解為countdownlatch有乙個正數計數器,countdown方法對計數器做減操作,await方法等待計數器達到0。所有aw...