ReentrantLock一个可重入的互斥锁
- 使用方法
class X {
- private final ReentrantLock lock = new ReentrantLock();
- // ...
- - public void m() {
- lock.lock(); // block until condition holds
- try {
- // ... method body
- } finally {
- lock.unlock()
- }
- }
内部实现依赖AbstractQueuedSynchronizer,有两种实现分别是公平锁,非公平锁
- 公平锁实现
final void lock() {
acquire(1);
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
tryAcquire
protected final boolean tryAcquire(int acquires) {
/**
* 获取当前线程
*/
final Thread current = Thread.currentThread();
/**
* 获取状态
*/
int c = getState();
/**
* 如果状态是0代表锁还没被线程持有
*/
if (c == 0) {
/**
* 判断头结点和尾结点不等 并且头结点的下一个结点为null或者头结点线程不为当前线程
* 通过cas改变state的值为acquires(1)
* 赋值当前线程等于exclusiveOwnerThread
*
* 第一次线程进入不会获取锁,会记录线程
* synchronized抄袭偏向锁原理
*
*/
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
/**
* 进入这里代表该线程已经为独占锁模式
* 只要将state递增就行
*/
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
addWaiter
private Node addWaiter(Node mode) {
/**
* 赋值Node的成员变量
* thread和nextWaiter
*/
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
/**
* 通过cas尝试一次添加尾结点
* 如果失败再进行自旋
*/
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
enq
private Node enq(final Node node) {
for (;;) {
Node t = tail;
//第一次进方法一定是null
if (t == null) {
/**
* 如果尾部节点为nul
* 必须初始化
*/
if (compareAndSetHead(new Node()))
tail = head;
// 执行完tail就等于head
} else {
// 赋值node的前一个结点为当前的尾结点
node.prev = t;
// cas重新赋值尾结点为node
if (compareAndSetTail(t, node)) {
// 之前尾结点的下一个结点为当前的尾结点(就是node)
t.next = node;
return t;
}
}
}
}
acquireQueued
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//获取前一个节点
final Node p = node.predecessor();
//这里还会尝试去拿锁
if (p == head && tryAcquire(arg)) {
/**
* 成功获取锁,设置头结点为当前结点
*/
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
shouldParkAfterFailedAcquire
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
/**
* 第一次进来waitStatus是0将waitStatus设置为SIGNAL
* 通过自旋再尝试获取锁
*
*
*/
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* 这个节点已经设置了状态,要求释放信号,所以它可以安全地停放。
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus 必须为 0 或 PROPAGATE。
* 表明我们需要一个信号,但不要停车。呼叫者将需要重试以确保其无法在停车前获取。
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
parkAndCheckInterrupt
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
park(Object blocker)
public static void park(Object blocker) {
Thread t = Thread.currentThread();
/**
* 关联当前线程的成员属性parkBlocker锁对象
*/
setBlocker(t, blocker);
/**
* liunx通过pthread_cond_wait
* windows通过WaitForSingleObject
* 将线程暂时挂起
*/
UNSAFE.park(false, 0L);
/**
* 设置线程的parkBlocker为null
*/
setBlocker(t, null);
}
unlock
public void unlock() {
sync.release(1);
}
release
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
tryRelease
protected final boolean tryRelease(int releases) {
// 获取锁计数。
int c = getState() - releases;
// 如果当前线程不是此锁的持有者,则抛出 {@link IllegalMonitorStateException}。
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 如果保持计数现在为零,则锁定被释放。
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
// 如果当前线程是此锁的持有者,则持有计数递减。
setState(c);
return free;
}
unparkSuccessor
private void unparkSuccessor(Node node) {
/*
* 如果状态为负(即可能需要信号),请尝试清除以期待信号。
* 如果此操作失败或等待线程更改状态,则可以。
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* unpark 的线程保留在后继节点中,通常只是下一个节点。
* 但如果被取消或明显为空,则从尾部向后遍历以找到实际的未取消后继者。
*/
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);
}
- 非公平锁实现
final void lock() {
/**
* 直接cas尝试获取锁
*/
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}