Java開發中synchronized的定義及用法
synchronized是java中用於同步的關鍵字,其典型的作用域如下所示.
1 物件鎖
@Slf4jpublic class SynchronizedExample1 {
private final int loopNum = 20; // 修飾一個程式碼塊
private void test1(int j) {
synchronized (this) {
for (int i = 0; i < loopNum; i++) {
log.info(“test1 {} - {}”, j, i);
}
}
} // 修飾一個方法
private synchronized void test2(int num) {
for (int i = 0; i < loopNum; i++) {
}
} public static void main(String[] args) {
SynchronizedExample1 example1 = new SynchronizedExample1();
SynchronizedExample1 example2 = new SynchronizedExample1();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> { example1.test2(1); }); executorService.execute(() -> { example2.test2(2); }); executorService.shutdown(); }
}
1.1 程式碼塊修飾(物件)
此時,synchronized用於保證test1函式中的被synchronized大括號包裹的程式碼同步執行.
synchronized作用的物件為SynchronizedExample1的物件例項,例如main函式中的example1以及example2.Tips:
1.example1若在多個執行緒中被呼叫,其輸出順序將保證同步,按照1,2,3…19,20的順序執行.
2.若example1與example2均在多個執行緒中執行,則test1…之間保持同步輸出,test2…之間保持同步輸出,但是test1…與test2…之間輸出不保證順序.1.2 非靜態函式修飾synchronized添加於test2函式宣告中,其作用類似於1.1中的程式碼塊修飾,區別點僅僅在於其同步程式碼塊擴充至整個函式(test2).
2. 類鎖
@Slf4jpublic class SynchronizedExample2 {
private static final int loopNum = 20; // 修飾一個類
private static void test1(int j) {
synchronized (SynchronizedExample2.class) {
for (int i = 0; i < loopNum; i++) {
log.info(“test1 {} - {}”, j, i);
}
}
} // 修飾一個靜態方法
private static synchronized void test2(int j) {
for (int i = 0; i < loopNum; i++) {
log.info(“test2 {} - {}”, j, i);
}
} public static void main(String[] args) {
SynchronizedExample2 example1 = new SynchronizedExample2();
SynchronizedExample2 example2 = new SynchronizedExample2();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
example1.test1(1);
});
executorService.execute(() -> {
example2.test1(2);
});
}
}
2.1 程式碼塊修飾(類)與1.1中區別在於,synchronized函式修飾的是SynchronizedExample2類.
SynchronizedExample2物件,諸如example1或者example2在任意多的執行緒中呼叫test1函式,其輸出順序均會被保證(1,2,3,4…19,20).
2.2 靜態函式修飾功能與2.1類似,均是對物件加鎖,確保多個類物件呼叫函式時保持順序.Tips:
示例中,因為類上加鎖的原因,test1與test2物件保持順序執行,不會出現test1…與test2…交叉出現的現象.
3 synchronized不能被繼承
需要注意,若synchronized修飾於函式中,如1.2以及2.2,若有類繼承於SynchronizedExample1或者SynchronizedExample1,子類物件呼叫test2不同步.原因:synchronized非函式簽名,因此無法被繼承,所以無法保證子類呼叫同步.
文章來自:https://www.itjmd.com/news/show-5319.html