1. ReentrantLock简介
ReentrantLock即重入锁,是Lock接口类的一个实现类,通过内部类Sync实现了AQS。相比较Synchronized而言,都是可重入锁,不同点在于ReentrantLock可以更加灵活,Synchronized的加锁和解锁都有JVM完成。
2. ReetrantLock的原理
2.1 非公平锁
非公平锁是默认的获取锁的方式。
非公平锁在获取同步状态时,通过判断当前线程是否为获取锁的线程,如果是获取锁的线程则将同步值进行增加并返回true,表示获取同步状态成功。
final boolean nonfairTryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();
//获取当前线程的同步状态state
int c = getState();
//state为0表示当前锁没有被其他线程占用
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;
}
复制代码
2.2 公平锁
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//当前线程的同步状态为0,尝试获取锁
if (c == 0) {
//判断CLH队列中是否有其他线程,如果没有当前线程获取锁成功,当前线程需要等待
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;
}
}
复制代码
公平锁和非公平锁的获取的不同点在于:公平锁会判断CLH队列中是否还有其他线程,而非公平锁会直接尝试进行CAS操作修改同步状态。
2.3 锁的释放
当同步状态为0的时候才释放锁,之前的操作都会返回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;
}
复制代码
ReentrantLock | Synchronized | |
---|---|---|
锁实现机制 | 依赖AQS | 监视器模式 |
灵活性 | 支持响应中断、超时、尝试获取锁 | 不灵活 |
释放形式 | 必须显示调用unlock()释放锁 | 自动释放监视器 |
锁类型 | 公平锁&非公平锁 | 非公平锁 |
条件队列 | 可关联多个条件队列 | 关联一个条件队列 |
可重入性 | 可重入 | 可重入 |
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END