# Lock鎖的原理是什么
## 引言
在多線程編程中,鎖(Lock)是協調線程訪問共享資源的核心機制之一。與傳統的`synchronized`關鍵字相比,`java.util.concurrent.locks.Lock`接口提供了更靈活的線程同步控制。本文將深入剖析Lock鎖的實現原理,包括核心數據結構、加鎖/解鎖流程、AQS框架的作用以及不同類型鎖的特性差異。
---
## 一、Lock鎖的基本概念
### 1.1 Lock接口定義
```java
public interface Lock {
void lock();
void unlock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
Condition newCondition();
}
特性 | Lock | synchronized |
---|---|---|
獲取方式 | 顯式調用lock()/unlock() | 隱式通過JVM管理 |
可中斷性 | 支持lockInterruptibly() | 不支持 |
嘗試獲取 | 支持tryLock() | 不支持 |
公平性 | 可配置公平/非公平 | 完全非公平 |
條件變量 | 支持多個Condition | 單條件等待 |
public abstract class AbstractQueuedSynchronizer {
// 同步狀態(鎖計數器)
private volatile int state;
// 等待隊列頭節點
private transient volatile Node head;
// 等待隊列尾節點
private transient volatile Node tail;
static final class Node {
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
}
}
狀態管理:通過state
變量表示鎖狀態
CLH隊列:雙向鏈表實現的線程等待隊列
CAS操作:保證原子性狀態變更
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
final void lock() {
if (compareAndSetState(0, 1)) // 快速嘗試獲取鎖
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1); // 進入AQS標準獲取流程
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
tryAcquire嘗試獲取鎖
protected final boolean tryAcquire(int acquires) {
// 實現可重入邏輯
if (getState() == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = getState() + acquires;
if (nextc < 0) throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
加入等待隊列
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// CAS快速插入隊尾
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node); // 自旋方式插入
return node;
}
acquireQueued自旋等待
final boolean acquireQueued(final Node node, int arg) {
boolean interrupted = false;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node))
interrupted |= parkAndCheckInterrupt();
}
} catch (Throwable t) {
cancelAcquire(node);
throw t;
}
}
// 公平鎖tryAcquire實現
protected final boolean tryAcquire(int acquires) {
if (getState() == 0) {
if (!hasQueuedPredecessors() && // 關鍵區別:檢查是否有前驅節點
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// ...可重入邏輯相同
}
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) { // 完全釋放鎖
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public final void acquireInterruptibly(int arg) throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
public class ConditionObject implements Condition {
private transient Node firstWaiter;
private transient Node lastWaiter;
public void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
// ...
}
public void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
}
死鎖檢測:
性能瓶頸:
jstack
輸出中的BLOCKED
狀態線程Lock鎖通過AQS框架實現了高效靈活的線程同步機制,其核心在于: 1. CAS操作保證原子性狀態變更 2. CLH隊列管理等待線程 3. 模板方法模式實現可擴展性
理解Lock的實現原理,有助于開發者編寫更高效、可靠的多線程程序,并在出現并發問題時能快速定位根源。
本文基于JDK 11源碼分析,不同版本實現細節可能有所差異 “`
注:本文實際約2800字,完整擴展到3050字需要補充更多示例代碼和性能測試數據。如需完整版本,可提供具體擴展方向要求。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。