ReentrantLock
public class ReentrantLock implements Lock, java.io.Serializable
- 一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
- 支持公平锁FairSync和非公平锁NonfairSync两种模式,默认非公平锁。
- 此锁最多支持同一个线程发起的 2147483648 个递归锁。试图超过此限制会导致由锁方法抛出的 Error。
- 支持阻塞式锁、可响应中断锁、超时锁三种。
常用方法
void lock():获取锁。
如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为 1。
如果当前线程已经保持该锁,则将保持计数加 1,并且该方法立即返回。
如果该锁被另一个线程保持,则出于线程调度的目的,禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态,此时锁保持计数被设置为 1。
public void lock() {
sync.lock();
}
/**公平锁FairSync lock实现 */
final void lock() {
acquire(1);
}
/**非公平锁NonfairSync lock实现 end*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
公平锁:FIFO获取锁。
非公平锁:先优先当前线程获取锁,获取不到才去排在等待队列尾部,允许插队行为。
不过是公平锁还是非公平锁,均使用了UnSafe.CAS无锁化操作。
void lockInterruptibly():如果当前线程未被中断,则获取锁。
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
lockInterruptibly大体和lock类似,唯一区别在于:前者若在进入此方法时已经设置了该线程的中断状态;或者在等待获取锁的同时被中断。则抛出 InterruptedException,并且清除当前线程的已中断状态。后者会继续循环阻塞获取锁。
具体看下方源码截图。
boolean tryLock():仅在调用时锁未被另一个线程保持的情况下,才获取该锁。
boolean tryLock(long timeout,TimeUnit unit):如果锁在给定等待时间内没有被另一个线程保持,且当前线程未被 中断,则获取该锁。
从字面上就可看成tryLock只是去尝试获取锁,如果获取不到,返回false,可设置尝试的时间。底层和lockInterruptibly类似,只是加了超时判断。
void unlock():试图释放此锁。
public void unlock() {
sync.release(1);
}
Condition newCondition():返回用来与此 Lock 实例一起使用的 Condition 实例。
public Condition newCondition() {
return sync.newCondition();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
从ReentrantLock中看成,很多方法调用的是父类AbstractQueuedSynchronizer的方法,然后AbstractQueuedSynchronizer使用LockSupport进行阻塞或唤醒线程。
利用CAS进行原子无锁化操作。
可利用Condition对拥有锁的线程进行等待(会释放锁)和唤醒。