主要明白一點: synchronized static 被鎖定的是同一塊區域,爲啥?由於static修飾的變量和方法在內存中都是惟一的java
package Thread; import java.util.concurrent.CountDownLatch; public class TestSynStatic { /** * 當每一個線程都new出來一個對象時,線程在執行時會建立本身的字段 i 和 add1 的副本,是線程安全的。 * 當每一個線程都共用new出來的一個對象時,不是線程安全的。 */ int i = 0; public void add1(){ for (int i1 = 0; i1 < 100; i1++) { i++; } System.out.println("i:" + i); } /** * 存在在安全性問題, static 關鍵詞修飾的變量會被線程共享,該變量 j 放在JVM的靜態區域共享 */ static int j = 0; public void add2(){ for (int i1 = 0; i1 < 100; i1++) { j++; } System.out.println("j:" + j); } /** * 存在在安全性問題, static 關鍵詞修飾的變量,該變量 k 放在JVM的靜態區域被多線程共享 * 鎖定的是新的實例 * 當每一個線程都共用new出來的一個對象時,是線程安全的。 * 當每一個線程都new出來一個對象時,不是線程安全的。 */ static int k = 0; public synchronized void add3(){ for (int i1 = 0; i1 < 100; i1++) { k++; } System.out.println("k:" + k); } /** * 鎖定的是JVM中的類,注意不是JVM中new出來的對象,線程安全 */ static int m = 0; public synchronized static void add4(){ for (int i1 = 0; i1 < 100; i1++) { m++; } System.out.println("m:" + m); } public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(50); TestSynStatic testSynStatic = new TestSynStatic(); for (int i = 0; i < 50; i++) { new Thread(() -> { // TestSynStatic testSynStatic = new TestSynStatic(); // testSynStatic.add1(); // testSynStatic.add2(); // testSynStatic.add3(); // 鎖定的是新的實例,不是線程安全的。 testSynStatic.add4(); // 鎖定的是JVM中的類,線程安全 countDownLatch.countDown(); }).start(); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } }