您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。