| 工具 | 層級 | 核心特性 | 適用場景 | 效能 |
|---|---|---|---|---|
volatile | 關鍵字 | 可見性 + 禁止指令重排,無原子性 | 狀態標記、雙重檢查鎖、單次寫入多讀 | 極高(無鎖) |
synchronized | 關鍵字/監視器 | 可重入、公平性弱、JVM 優化深(偏向鎖、輕量級鎖、膨脹) | 一般同步、鎖競爭不激烈、代碼簡潔優先 | 中(JDK 6+ 優化後接近 Lock) |
ReentrantLock | API (AQS) | 可中斷、可超時、公平/非公平、條件變量 | 高並發、複雜同步邏輯、需中斷/超時控制 | 高(非公平模式) |
ReentrantReadWriteLock | API (AQS) | 讀共享/寫獨享、降級支援、可重入 | 讀多寫少、緩存、配置熱加載 | 高(讀並行) |
StampedLock | API (JDK 8) | 樂觀讀、無條件變量、不可重入 | 極高讀並發、無寫入衝突場景 | 極高 |
Semaphore | API (AQS) | 計數許可證、公平/非公平 | 資源池限流、連接池、並發任務控制 | 中 |
CountDownLatch | API (AQS) | 一次性倒計時門闂 | 多線程啟動同步、分階段等待 | 高 |
CyclicBarrier | API (AQS) | 可重置循環屏障、可選屏障動作 | 並行計算分階段匯總、遊戲關卡同步 | 中 |
CompletableFuture | API (JDK 8) | 非阻塞組合、異步流水線、異常傳播 | 異步編排、多服務聚合、響應式編程 | 高 |
// 1. 同步代碼塊:縮小鎖粒度
public void transfer(Account from, Account to, int amount) {
Object lock1 = from.hashCode() < to.hashCode() ? from : to;
Object lock2 = from.hashCode() < to.hashCode() ? to : from;
synchronized (lock1) {
synchronized (lock2) { // 固定順序防死鎖
from.withdraw(amount);
to.deposit(amount);
}
}
}
// 2. 靜態方法鎖住 Class 對象
public static synchronized void staticMethod() { }
// 3. wait/notify 經典模式:生產者消費者
synchronized (queue) {
while (queue.isEmpty()) queue.wait(); // 必須在循環中檢查條件
Item item = queue.poll();
queue.notifyAll(); // 喚醒所有等待者
}
private final Lock lock = new ReentrantLock(); // 非公平鎖,效能優
public void doWork() {
if (lock.tryLock(5, TimeUnit.SECONDS)) { // 帶超時,防死等
try {
// 關鍵區段
} finally {
lock.unlock(); // 必須在 finally 中釋放
}
} else {
log.warn("獲取鎖超時");
}
}
// 可中斷鎖:響應線程中斷
public void interruptibleWork() throws InterruptedException {
lock.lockInterruptibly();
try { /* ... */ } finally { lock.unlock(); }
}
class BoundedQueue<E> {
private final Lock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
private final Queue<E> queue = new ArrayDeque<>();
private final int capacity;
public void put(E e) throws InterruptedException {
lock.lockInterruptibly();
try {
while (queue.size() == capacity) notFull.await();
queue.add(e);
notEmpty.signal(); // 喚醒一個消費者
} finally { lock.unlock(); }
}
public E take() throws InterruptedException {
lock.lockInterruptibly();
try {
while (queue.isEmpty()) notEmpty.await();
E e = queue.poll();
notFull.signal(); // 喚醒一個生產者
return e;
} finally { lock.unlock(); }
}
}
class ResourcePool<T> {
private final Semaphore available;
private final Queue<T> pool = new ConcurrentLinkedQueue<>();
public ResourcePool(int maxSize, Supplier<T> factory) {
available = new Semaphore(maxSize, true);
for (int i = 0; i < maxSize; i++) pool.add(factory.get());
}
public T acquire() throws InterruptedException {
available.acquire(); // 獲取許可
T resource = pool.poll();
if (resource == null) resource = createNew(); // 池空時動態創建
return resource;
}
public void release(T resource) {
pool.add(resource);
available.release(); // 釋放許可
}
}
CAS(V, E, N):比較並交換。僅當內存值 V 等於預期值 E 時,原子更新為新值 N。失敗不阻塞,重試或放棄。
// 100 萬次計數,3 線程
AtomicInteger atomic = new AtomicInteger(0);
// vs
synchronized int count = 0;
// 結果:Atomic ~45ms,synchronized ~200ms(4-5 倍差距)
// 原因:CAS 用戶態完成,無內核態切換、無線程掛起/喚醒
AtomicInteger、AtomicLong、AtomicBoolean、AtomicReferenceAtomicIntegerArray、AtomicReferenceArrayAtomicIntegerFieldUpdater、AtomicReferenceFieldUpdater(反射式,無需修改類)LongAdder、DoubleAdder(JDK 8,高併發計數器,分段 CAS,效能碾壓 AtomicLong)
// 請求上下文傳遞
public class RequestContext {
private static final ThreadLocal<Context> HOLDER = new ThreadLocal<>();
public static void set(Context ctx) { HOLDER.set(ctx); }
public static Context get() { return HOLDER.get(); }
public static void clear() { HOLDER.remove(); } // 必須清理,防內存洩漏
}
// SimpleDateFormat 非線程安全,ThreadLocal 獨享
private static final ThreadLocal<DateFormat> DATE_FORMAT = ThreadLocal.withInitial(
() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
);
注意:線程池場景必須在任務結束時 `remove()`,否則上下文洩漏到下一任務。
LongAdder/AtomicLongvolatile 或 StampedLock 樂觀讀ReentrantReadWriteLock 或 StampedLockReentrantLocksynchronizedCompletableFuture / Reactor / RxJava