多執行緒同時存取**共享可變狀態**(臨界資源)導致資料競爭。核心目標:**保證操作原子性、可見性、有序性**。典型場景:資金轉帳、庫存扣減、資料庫事務。
class Output {
public void print(String name) {
for (char c : name.toCharArray()) System.out.print(c);
System.out.println();
}
}
// 無同步 → 輸出交錯:zhangsanluxiaofeng...
public void print(String name) {
synchronized (this) { // 鎖住當前實例
for (char c : name.toCharArray()) System.out.print(c);
System.out.println();
}
}
public synchronized void print(String name) { // 等同於 synchronized(this)
for (char c : name.toCharArray()) System.out.print(c);
System.out.println();
}
public static synchronized void print2(String name) {
// 鎖為 Class 物件:Output.class
for (char c : name.toCharArray()) System.out.print(c);
System.out.println();
}
關鍵差異:實例方法鎖 `this`,靜態方法鎖 `Class` 物件。若同時存取同一實例的實例/靜態同步方法,**互不阻塞**(鎖不同),需統一鎖物件。
class FineGrained {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
private int count1, count2;
public void inc1() { synchronized(lock1) { count1++; } }
public void inc2() { synchronized(lock2) { count2++; } }
}
不同資料用不同鎖,提升並發度。
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public void read() { rwLock.readLock().lock(); try { ... } finally { rwLock.readLock().unlock(); } }
public void write() { rwLock.writeLock().lock(); try { ... } finally { rwLock.writeLock().unlock(); } }
讀讀並發、讀寫互斥、寫寫互斥,適合「讀多寫少」場景。
ThreadLocal:執行緒獨享副本,零競爭AtomicInteger 等 CAS 類:硬體級原子操作| 坑 | 後果 | 修正 |
|---|---|---|
| 用 String 常量/基本型別包裝類作鎖 | 全 JVM 共享同一把鎖,誤阻塞無關代碼 | 用 `private final Object lock = new Object()` |
| 同步方法中調用異步/耗時操作 | 長時間持有鎖,吞吐率暴跌 | 縮小同步範圍,耗時操作移出同步塊 |
| Double-Checked Locking 未加 volatile | 指令重排導致單例失效 | `private static volatile Instance inst` |
| 集合迭代時併發修改 | ConcurrentModificationException | 用 CopyOnWriteArrayList、ConcurrentHashMap 或同步迭代 |