ReentrantLock和synchronized在jdk1.8版本后性能相差无几,甚至synchronized小优,但是synchronized不支持中断和超时,也就是说通过synchronized一旦被阻塞住,如果一直无法获取到所资源就会一直被阻塞,即使中断也没用,这对并发系统的性能影响太大了;Lock支持中断和超时、还支持尝试机制获取锁,对synchronized进行了很好的扩展,所以从灵活性上Lock是明显优于synchronized的
基本方法
// 构造方法
// boolean fair 是否为公平锁
ReentrantLock(boolean fair)
// 尝试拿锁,拿不到阻塞等待
void lock();
// 释放锁
void unlock();
// 等待拿锁的时间可被中断
void lockInterruptibly() throws InterruptedException;
// 尝试拿锁,不等待
boolean tryLock();
// 尝试拿锁,等待timeout时间
boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException;
公平锁
拿锁
final void lock() {
acquire(1);
}
public final void acquire(int arg) {
// 首先尝试拿锁
if (!tryAcquire(arg) &&
// addWaiter 拿锁失败时候 加入(创建)请求队列
// acquireQueued 在一个死循环中 判断是否是队列头 并尝试拿锁,否则阻塞 LockSupport.park(this)
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//尝试拿锁
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 当前锁状态为空闲
// hasQueuedPredecessors 当前线程是否需要排队(公平锁) true: 需要, false: 不需要
if (!hasQueuedPredecessors() &&
// 通过 CAS 拿锁
compareAndSetState(0, acquires)) {
// 成功拿到锁之后设置当前持有锁的线程为当前线程
setExclusiveOwnerThread(current);
return true;
}
}
// 当前有线程持有锁
// 判断当前持有锁的线程是否是当前线程
else if (current == getExclusiveOwnerThread()) {
// 是当前线程 则 c + 1 (可重入)
int nextc = c + 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);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
// 判断当前请求队列是否存在
if (pred != null) {
// 队列存在 则直接加入队尾
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// 队列不存在 创建队列 并 将当前请求放入队列
enq(node);
return node;
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
// 死循环
for (;;) {
// 拿到当前线程的prev
final Node p = node.predecessor();
// 若 prev 是头部 则尝试拿锁
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 判断当前线程请求状态是否应该 park
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) // 阻塞 LockSupport.park(this);
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
释放锁
public final boolean release(int arg) {
// 释放锁
if (tryRelease(arg)) {
Node h = head;
// 释放成功后 将请求队列的 head 节点 unpark 唤醒
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
// 锁定次数 - 1
int c = getState() - releases;
// 判断当前线程是否是当前持有锁的线程
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 如果 c == 0 则 当前锁为空闲状态
if (c == 0) {
free = true;
// 设置持有锁的线程为空
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
非公平锁
final void lock() {
// 尝试拿锁 (插队)
if (compareAndSetState(0, 1))
// 拿锁成功 设置当前持有锁的线程为当前线程
setExclusiveOwnerThread(Thread.currentThread());
else
// 此方法与公平锁使用同一个方法
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 此处没有判断请求队列 直接拿锁 (插队)
// 就没有很严格的先后顺序,
// 但是和公平锁一样是存在请求队列
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}