ReentrantLock是JUC提供的可重入锁,与synchronized提供相似的功能,但是ReentrantLock和synchronized之间还是存在一些异同:
· synchronized是独占锁,加解锁过程自动进行,易用但不灵活。ReentrantLock是JUC提供的独占锁,加解锁过程手动进行,不易用但灵活。
· ReentrantLock和synchronized均是重入锁,synchronized由于是语言级提供,不必担心加解锁的过程。ReentrantLock由于是JUC提供,加解锁过程需尤为慎重,否则会导致锁泄漏。
· synchronized不可响应中断,若线程获取不到锁,会一直阻塞。ReentrantLock可以响应中断。
· ReentrantLock提供公平锁和非公平锁,为特定业务场景提供了更完善的解决方案。
演示示例:
首先,新建线程类,在线程类中加入获取锁和释放锁的操作:
package com.securitit.serialize.locks;
import java.util.concurrent.locks.Lock;
public class ReentrantLockThread extends Thread {
// 锁实例.
private Lock lock;
// 构造方法.
public ReentrantLockThread(Lock lock) {
this.lock = lock;
}
@Override
public void run() {
try {
// 获取锁.
lock.lock();
System.out.println(Thread.currentThread().getName() + ":获得锁.");
Thread.sleep(5000);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + ":释放锁.");
// 释放锁.
lock.unlock();
}
}
}
然后,新建测试类,创建一个ReentrantLock实例,启动多线程用以模拟多线程环境下锁的获取和释放操作是否符合预期:
package com.securitit.serialize.locks;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockTester {
private static Lock lock = new ReentrantLock();
public static void main(String[] args) throws Exception {
// 新建多个多线程,用以模拟多线程环境.
new ReentrantLockThread(lock).start();
new ReentrantLockThread(lock).start();
new ReentrantLockThread(lock).start();
new ReentrantLockThread(lock).start();
}
}
输出结果:
Thread-0:获得锁.
Thread-0:释放锁.
Thread-1:获得锁.
Thread-1:释放锁.
Thread-2:获得锁.
Thread-2:释放锁.
Thread-3:获得锁.
Thread-3:释放锁.
从结果可以看出,多个线程在竞争同一个ReentrantLock时,只有一个线程可以成功获得锁,其他线程在持有锁的线程释放锁后才可以竞争锁并获得锁。
源码分析:
实现基础:
ReentrantLock的实现基础是之前介绍过的AQS,在ReentrantLock内部定义了一个内部类Sync,其实现了锁的操作:
abstract static class Sync extends AbstractQueuedSynchronizer {
// 序列化版本号.
private static final long serialVersionUID = -5179523762034025860L;
// 获取锁抽象方法.
abstract void lock();
// 非公平锁获取独占锁.
final boolean nonfairTryAcquire(int acquires) {
// 取得当前线程.
final Thread current = Thread.currentThread();
// 获取当前Sync的state.
int c = getState();
// 若state=0,则直接调用AQS方法进行加锁.
if (c == 0) {
// 尝试更新state=acquires.
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;
}
// 尝试释放锁.
protected final boolean tryRelease(int releases) {
// 获得释放锁后的state.
int c = getState() - releases;
// 若当前线程未获得独占锁.
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
// 设置null获取了独占锁.
setExclusiveOwnerThread(null);
}
// 设置state.
setState(c);
return free;
}
// 当前线程是否获得了独占锁.
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
// 获得独占锁的Condition.
final ConditionObject newCondition() {
return new ConditionObject();
}
// 获得独占锁的持有线程.
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
// 获取等待独占锁的数量.
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
// 是否已加锁.
final boolean isLocked() {
return getState() != 0;
}
// 序列化操作.
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
在Sync的基础上,实现了FairSync和NonFairSync,即公平锁和非公平锁:
// 公平锁实现.
static final class FairSync extends Sync {
// 序列化版本号.
private static final long serialVersionUID = -3000897897090466540L;
// 获得独占锁.
final void lock() {
acquire(1);
}
// 尝试获取独占锁.
protected final boolean tryAcquire(int acquires) {
// 当前线程.
final Thread current = Thread.currentThread();
// 获得当前锁状态.
int c = getState();
// 当前锁未被线程占有.
if (c == 0) {
// 条件翻译:是否还有前置的等待者 && 以CAS方式设置锁状态 && 设置当前线程为锁的持有者.
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 当前线程是锁的持有者时,增加重入次数.
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
// 非公平锁实现.
static final class NonfairSync extends Sync {
// 序列化版本号.
private static final long serialVersionUID = 7316153563782823691L;
// 获得独占锁.
final void lock() {
// 以CAS方式更新锁状态 && 设置当前线程为锁的持有者.
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// 直接获取锁,没有会一直等待.
acquire(1);
}
// 尝试获得锁.
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
基本方法:
// 无参构造方法.默认非公平锁.
public ReentrantLock() {
sync = new NonfairSync();
}
// 指定公平锁或非公平锁创建ReentrantLock.
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
// 同步阻塞获得锁.
public void lock() {
sync.lock();
}
// 带响应中断的获取锁.
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
// 尝试获得锁.
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
// 指定等待时间的获得锁.
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
// 释放锁.
public void unlock() {
sync.release(1);
}
// 获得条件Condition.
public Condition newCondition() {
return sync.newCondition();
}
// 获取等待线程数量.
public int getHoldCount() {
return sync.getHoldCount();
}
// 当前线程是否锁持有者.
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
// 是否已经加锁.
public boolean isLocked() {
return sync.isLocked();
}
// 是否公平锁.
public final boolean isFair() {
return sync instanceof FairSync;
}
// 获取锁的持有者.
protected Thread getOwner() {
return sync.getOwner();
}
// 是否还有等待线程.
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
// 指定Thread是否在队列中.
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
// 获取队列长度.
public final int getQueueLength() {
return sync.getQueueLength();
}
// 获得所有的锁的集合.
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
// 指定Condition是否存在等待者.
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
// 指定Condition的
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
// 指定Condition,获得等待线程集合.
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
总结:
ReentrantLock在AQS的基础上实现了Sync,同时有两个FairSync和NonfairSync,也提供了Condition的实现,
在看懂AQS之后,ReentrantLock是相对来说很简单的,只是对AQS框架的应用,另外需要注意的是,锁获得以后,必须显示的释放掉,否则会出现死锁等现象。
注:文中源码均来自于JDK1.8版本,不同版本间可能存在差异。
如果有哪里有不明白或不清楚的内容,欢迎留言哦!