JDK 5 java.util.concurrent.locks 提供比 synchronized 更強大的鎖 API:**可中斷、可超時、公平/非公平、條件變數、讀寫分離**。本文實戰示範 ReentrantLock 獨佔鎖與 ReentrantReadWriteLock 讀寫鎖的核心用法。
class LockCounter {
private final Lock lock = new ReentrantLock(); // 預設非公平
private long value = 0;
private int ops = 0;
public void add(long v) {
lock.lock(); // 必須在 try 之前
try {
Thread.sleep(1000); // 模擬耗時操作
value += v;
ops++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock(); // 必須在 finally 釋放
}
}
public long getValue() { return value; }
public int getOps() { return ops; }
}
lock.lock();
try {
// 臨界區
} finally {
lock.unlock();
}
「讀讀共存、讀寫互斥、寫寫互斥」。適合**讀多寫少**場景 (快取、配置、註冊表)。
class RWCache {
private final ReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
private Map<String, String> data = new HashMap<>();
public String get(String key) {
r.lock();
try { return data.get(key); }
finally { r.unlock(); }
}
public void put(String key, String val) {
w.lock();
try { data.put(key, val); }
finally { w.unlock(); }
}
// 升級鎖 (Read → Write) 不支援,會死鎖,需釋放讀鎖再取寫鎖
}
import java.util.concurrent.*;
public class LockDemo {
static class RWTest {
final ReadWriteLock lock = new ReentrantReadWriteLock();
final Lock r = lock.readLock(), w = lock.writeLock();
int value = 0, writes = 0;
void write(int v) {
w.lock();
try {
System.out.printf("Write %d start%n", v);
Thread.sleep(500);
value += v; writes++;
System.out.printf("Write %d done%n", v);
} catch (InterruptedException e) { Thread.currentThread().interrupt(); }
finally { w.unlock(); }
}
String read() {
r.lock();
try {
System.out.println("Read start");
Thread.sleep(300);
return value + ":" + writes;
} catch (InterruptedException e) { Thread.currentThread().interrupt(); return "err"; }
finally { r.unlock(); }
}
}
public static void main(String[] args) throws Exception {
RWTest test = new RWTest();
ExecutorService es = Executors.newCachedThreadPool();
// 提交 2 寫 + 2 讀 + 1 寫
es.submit(() -> test.write(10));
es.submit(() -> test.write(20));
es.submit(() -> System.out.println("Read1: " + test.read()));
es.submit(() -> System.out.println("Read2: " + test.read()));
Future<String> last = es.submit(() -> { test.write(30); return "ok"; });
last.get(); // 等待最後寫入完成
es.shutdownNow();
System.out.println("Final: " + test.read());
}
}
Write 10 start
Write 10 done ← 寫鎖獨佔,第二個寫等待
Write 20 start
Write 20 done
Read start ← 讀鎖共享,兩個讀同時進行
Read start
Read1: 30:2
Read2: 30:2
Write 30 start ← 讀寫互斥,寫等待讀完成
Write 30 done
Final: 60:3
| 特性 | synchronized | ReentrantLock | ReentrantReadWriteLock |
|---|---|---|---|
| 可中斷獲取 | ❌ | lockInterruptibly() ✅ | ✅ |
| 超時獲取 | ❌ | tryLock(timeout) ✅ | ✅ |
| 公平鎖 | ❌ (JVM 內部) | new ReentrantLock(true) ✅ | new ReentrantReadWriteLock(true) ✅ |
| 條件變數 | wait/notify | newCondition() 多條件 ✅ | ✅ |
| 讀寫分離 | ❌ | ❌ | ✅ |
| 效能 (低爭用) | 極佳 (JVM 優化) | 略低 | 略低 |
synchronized (JVM 偏向鎖、輕量鎖、消除鎖優化)。ReentrantLock。ReentrantReadWriteLock。LongAdder / AtomicLong (無鎖 CAS)。