原子性提供了互斥通路,同一個時刻隻能有一個線程對其進行操作,Java裡能夠保持原子性的除了atomic包之外還有鎖
synchronized關鍵字:主要依賴jvm來實作鎖,在這個關鍵字的作用對象的作用範圍内隻能有一個線程來執行操作。
Lock:jdk提供的代碼層面的鎖,依賴特殊的cpu指令,比較有代表性的有ReentrantLock
synchronized是一種同步鎖,它修飾的對象主要有四種:
修飾代碼塊(同步語句塊):大括号括起來的代碼,作用于調用的對象。
修飾方法(同步方法):整個方法,作用于調用的對象。
同步語句塊及同步方法的作用僅局限于調用的對象。即該鎖存在于同一個執行個體當中。示範如下:
@Slf4j
public class SynchronizedExample1 {
// 修飾一個代碼塊
public void test1(int j) {
synchronized (this) {
for (int i = 0; i < 10; i++) {
log.info("test1 {} - {}", j, i);
}
}
}
public static void main(String[] args) {
SynchronizedExample1 example1 = new SynchronizedExample1();
SynchronizedExample1 example2 = new SynchronizedExample1();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
example1.test1(1);
});
executorService.execute(() -> {
example2.test1(2);
});
}
}
檢視執行結果如下:
可以看到執行的結果是test1 0-9,test2 0-9。
分别建立兩個對象:
@Slf4j
public class SynchronizedExample1 {
// 修飾一個代碼塊
public void test1(int j) {
synchronized (this) {
for (int i = 0; i < 10; i++) {
log.info("test1 {} - {}", j, 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);
});
}
}
執行結果:
可以看到線程一和二是亂序執行的。說明鎖隻存在于調用的對象裡。
同理修飾一個方法執行代碼及結果如下:
@Slf4j
public class SynchronizedExample1 {
// 修飾一個方法
public synchronized void test2(int j) {
for (int i = 0; i < 10; i++) {
log.info("test2 {} - {}", j, i);
}
}
public static void main(String[] args) {
SynchronizedExample1 example1 = new SynchronizedExample1();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
example1.test2(1);
});
executorService.execute(() -> {
example1.test2(2);
});
}
}
執行結果如下:
分别建立兩個對象:
@Slf4j
public class SynchronizedExample1 {
// 修飾一個方法
public synchronized void test2(int j) {
for (int i = 0; i < 10; i++) {
log.info("test2 {} - {}", j, 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);
});
}
}
執行結果如下:
修飾靜态方法:整個靜态方法,作用于所有對象。
修飾類:括号括起來的部分,作用于所有對象。
修飾類示例如下:
@Slf4j
public class SynchronizedExample2 {
// 修飾一個類
public static void test1(int j) {
synchronized (SynchronizedExample2.class) {
for (int i = 0; i < 10; i++) {
log.info("test1 {} - {}", 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);
});
}
}
執行結果如下:
修飾靜态方法示例如下:
@Slf4j
public class SynchronizedExample2 {
// 修飾一個靜态方法
public static synchronized void test2(int j) {
for (int i = 0; i < 10; 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.test2(1);
});
executorService.execute(() -> {
example2.test2(2);
});
}
}
執行結果如下:
可以看到,即使是不同執行個體,它們之間仍然能順序執行。是以修飾靜态方法和修飾類,它作用于所有對象。
注意:子類繼承父類是帶不上synchronized關鍵字,synchronized是不屬于方法聲明的一部分。如果子類也想用synchronized需要自己顯示聲明。
synchronized、Lock、Atomic原子性對比:
synchronized:不可中斷鎖,一旦代碼執行到其作用範圍内是必須等待代碼執行完畢。适合競争不激烈,可讀性好。在競争激烈時,性能急劇下降。
Lock:可中斷鎖,多樣化同步,比如有時間限制同步。競争不激烈時,性能稍比synchronized差。競争激烈時能夠維持常态(對于相同的代碼,不斷提高請求(或并發)時,平均處理速度上變化不大)
Atomic包:競争不激烈時,性能稍比synchronized差,競争激烈時能維持常态。比lock性能好,但是隻能同步一個值。
是以,寫同步的時候,優先考慮synchronized,如果有特殊需要,再進一步優化。ReentrantLock和Atomic如果用的不好,不僅不能提高性能,還可能帶來災難。
想要檢視各測試結果,可以參看https://blog.csdn.net/z69183787/article/details/48420643