概述
ReentrantLock 是一种可重入的互斥锁,具有与使用 synchronized 方法和语句访问的隐式监视器锁相同的基本行为和语义,但具有扩展功能。 ReentrantLock 由上一个成功锁定但尚未解锁的线程拥有。当锁未被另一个线程拥有时,调用 lock 的线程将成功获取锁并返回。如果当前线程已经拥有该锁,则该方法将立即返回。可以使用 isHeldByCurrentThread 和 getHoldCount 方法检查此情况。 此类的构造函数接受一个可选的公平参数。在发生竞争时设置为 true 时,锁优先考虑授予最长等待线程的访问权。否则,此锁不保证任何特定的访问顺序。使用许多线程访问的公平锁的程序可能显示出较低的总吞吐量(即较慢;通常要慢得多),但具有较小的获取锁的时间差异和保证缺乏饥饿的可能性。但是,请注意,锁的公平性并不保证线程调度的公平性。因此,使用公平锁的许多线程之一可能在连续多次获得它,而其他活动线程并未进行并当前未持有该锁。另请注意,未定时的 tryLock()方法不遵守公平设置。如果锁可用,即使其他线程正在等待,它也会成功。 建议的做法是总是在调用 lock 之后立即使用 try 块,通常是在 before/after 结构中,如下所示:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock();
}
}
}
除了实现 Lock 接口外,此类还定义了许多用于检查锁状态的公共和保护方法。其中一些方法仅对工具和监控有用。 此类的序列化行为与内置锁的行为相同:反序列化的锁在解锁状态,而不管在序列化时的状态如何。 此锁支持同一线程的最多 2147483647 个递归锁。尝试超过此限制将导致锁定方法抛出 Error。
同步方式主要由 继承 AbstractQueuedSynchronizer的Sync实现,同时实现的公平锁和非公平锁
公平锁和非公平锁
在加锁的时候会先调用initialTryLock方法,对于公平锁来说要判断它前面有没有排队的线程才有可能获取到锁,非公平锁的情况先来尝试下获取锁,苏果获取不到才加入到队列
final void lock() {
if (!initialTryLock())
acquire(1);
}
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final boolean initialTryLock() {
Thread current = Thread.currentThread();
if (compareAndSetState(0, 1)) { // first attempt is unguarded
setExclusiveOwnerThread(current);
return true;
} else if (getExclusiveOwnerThread() == current) {
int c = getState() + 1;
if (c < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(c);
return true;
} else
return false;
}
/**
* Acquire for non-reentrant cases after initialTryLock prescreen
*/
protected final boolean tryAcquire(int acquires) {
if (getState() == 0 && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
}
公平锁
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
/**
* Acquires only if reentrant or queue is empty.
*/
final boolean initialTryLock() {
Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedThreads() && compareAndSetState(0, 1)) {
setExclusiveOwnerThread(current);
return true;
}
} else if (getExclusiveOwnerThread() == current) {
if (++c < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(c);
return true;
}
return false;
}
/**
* Acquires only if thread is first waiter or empty
*/
protected final boolean tryAcquire(int acquires) {
if (getState() == 0 && !hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
}
使用场景
分享到: