welcome to Tong's Digital Garden
bigguaiwutong@qq.com
by tong
ReentrantLock 基于 AQS,实现了公平锁和非公平锁,在开发中可以用它对共享资源进行同步。支持可重入,并且调度更加灵活,支持更多丰富的功能

Lock 是一个接口,只定义了 6 个方法
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
单个线程执行时重新进入同一个子程序仍然是线程安全的
一个线程可以不用释放而重复获取一个锁 n 次,只是在释放的时候也需要相应释放 n 次
在创建时会将其初始化,默认为 NoFairSync,也可以通过构造参数进行指定
继承自 AQS
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();
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;
}
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;
}
protected final boolean isHeldExclusively() {
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final boolean isLocked() {
return getState() != 0;
}
/**
* Reconstitutes the instance from a stream (that is, deserializes it). */
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
公平锁就是锁的分配会按照获取锁的顺序。非公平锁就是锁的分配不用按照请求锁的顺序,是抢占式的。
公平锁能保证排队的线程都能拿到锁,非公平锁是抢占式的,可能有些线程一直拿不到锁,处于阻塞状态,这种状态称为饥饿
为什么需要非公平锁:因为很多情况下,非公平锁的效率更高,因为非公平锁意味着后请求锁的线程可能在前面的休眠的线程恢复前拿到锁,有可能提高并发的性能。当唤醒挂起的线程时,线程状态切换之间会产生短暂的延时。非公平锁可以利用这段时间完成操作。
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}}
非公平锁只重写了 lock() 和 tryAcquire() 方法
lock():尝试一次获取锁,如果失败则调用 acquire() 方法
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) {
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;
}}
表示一个条件,不同线程可以通过该条件来进行通信。一个 Lock 对象可以关联多个 Condition 对象,多个线程可以被绑定在不同的 Condition 对象上,就可以分组等待唤醒。丰富了线程的调度策略