| 維度 | synchronized | Lock (java.util.concurrent.locks.Lock) |
|---|---|---|
| 功能覆蓋 | 基礎同步 | 涵蓋 synchronized 所有功能並擴展更多特性 |
| 線程語義 | 隱式獲取/釋放鎖 | 顯式 lock()/unlock(),需在 finally 中釋放 |
| 精確控制 | 不支援中斷、超時、公平鎖等 | 支援可中斷、超時等待、公平/非公平鎖、條件變量 |
| 效能表現 | JVM 優化後效能優異,低競爭下極快 | 高競爭下吞吐量通常優於 synchronized |
每個 Java 對象天生持有一把監視器鎖。JVM 維護一個計數器:
當多個同步塊鎖定同一對象(如 synchronized(this))時,無論位於不同方法,線程間均互斥執行。若鎖定不同對象實例,則無同步效果。
class Test {
public static User user = null;
public synchronized void add(User u) { // 鎖的是 Test.class 實例?錯!鎖的是 this
user = u;
Dao.save(user);
}
}
若兩線程分別 new Test(),則持有不同鎖,user 為 static 共享變量將發生競態。修正方式:
static synchronized void add(...) 鎖定 Class 對象ReentrantLock 實現跨實例同步class Test {
public static User user = null;
private final Lock lock = new ReentrantLock();
public void add(User u) {
lock.lock();
try {
user = u;
Dao.save(user);
} finally {
lock.unlock(); // 必須在 finally 釋放
}
}
}
此寫法無論 new 多少個 Test 實例,均共享同一把鎖,等效於 static synchronized,但提供更豐富的鎖操作語義。
synchronized(語法簡潔,JVM 深度優化)LockReentrantLock 通常吞吐更高