* A reentrant mutual exclusion {@link Lock} with the same basic * behavior and semantics as the implicit monitor lock accessed using * {@code synchronized} methods and statements, but with extended * capabilities.
一个可重入的互斥锁,它与使用synchronized的方法和语句来进行隐式锁访问的方式具有相同的基本行为和语义,但是同时具有一些扩展功能。
* <p>The constructor for this class accepts an optional * <em>fairness</em> parameter. When set {@code true}, under * contention, locks favor granting access to the longest-waiting * thread. Otherwise this lock does not guarantee any particular * access order. Programs using fair locks accessed by many threads * may display lower overall throughput (i.e., are slower; often much * slower) than those using the default setting, but have smaller * variances in times to obtain locks and guarantee lack of * starvation.
ReentrantLock构造方法接收一个可选的公平参数。当设置为true时,它是公平锁,这时锁会将访问权授予等待时间最长的线程。否则该锁将无法保证线程获取锁的访问顺序。公平锁与非公平锁相比,使用公平锁的程序会有较低的吞吐量,但使用公平锁能有效减少线程饥饿的发生。
使用建议:一般推荐的使用方式就是 lock()后紧跟try块,例如:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}}
一、源码解析
private final Sync sync;
/**
* Base of synchronization control for this lock. Subclassed
* into fair and nonfair versions below. Uses AQS state to
* represent the number of holds on the lock.
*/
abstract static class Sync extends AbstractQueuedSynchronizer
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync
以上为ReentrantLock提供的3个静态内部类,其中Sync类继承自AbstractQueuedSynchronizer(抽象队列同步器),而NonfairSync和FairSync为Sync类的两个实现,分别应用于非公平锁和公平锁的场景,而公平锁和非公平锁在释放锁的情况都是一样的,只是在获取锁时,公平锁会让等待最久的线程优先获取到锁,而非公平锁在获取锁时各线程机会均等,这样也就导致会出现饥饿现象产生.
static final class FairSync extends Sync
final void lock() {acquire(1);}
static final class NonfairSync extends Sync
{
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
}
以上为公平锁和非公平锁调用lock()的源码,其中的compareAndSetState,setExclusiveOwnerThread和acquire 均来自AQS中,有次可以看出非公平锁在lock时就会去尝试1次去获取锁,获取到了就返回,如果获取不到,则跟公平锁一样,调用acquire(arg)再次尝试获取锁,说白了,非公平锁比公平锁多1次抢占锁的动作。而在抢占动作中,非公平锁是直接尝试抢占,而公平锁会先判断是否位于头结点来决定是否抢占。
非公平锁获取锁源码
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 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;
}
二、使用场景
场景1 防止重复执行
ReentrantLock lock = new ReentrantLock();
if(lock.tryLock()){//如果已经被lock,则直接放回false,不会等待,达到忽略的效果
try
{
}finally {
lock.unlock();
}
}
场景2 串行执行(同步执行,类似synchronized)
try
{
lock.lock();
}finally {
lock.unlock();
}
场景3 超时等待
try{
if(lock.tryLock(5, TimeUnit.SECONDS)){
try
{
}finally {
lock.unlock();
}
}
}catch (InterruptedException ex){
ex.printStackTrace();
}
场景4 响应中断
try {
lock.lockInterruptibly();
} catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
lock.unlock();
}