Skip to content

ReentrantLock

对比 synchronize

  • 可中断
  • 可以设置超时时间
  • 可以设置为公平锁
  • 支持多个条件变量 waitset

与 synchronize 一样,都支持可重入

java
static ReentrantLock reentrantLock = new ReentrantLock();
public static void main(String[] args) {
    reentrantLock.lock();
    try {
        // todo something
    } finally {
        reentrantLock.unlock();
    }
}

可重入

可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁

如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住

API

方法含义
lock()加锁
不可中断,获取不到锁会无限等待
unlock()解锁
lockInterruptibly()如果没有竞争那么此方法就会获取Lock 对象锁
如果有竞争就进入阻塞队列,可以被其他线程用interrupt打断
boolean tryLock()尝试获取锁,如果没有获取锁则直接失败
boolean tryLock(int timeout, TimeUnit unit)尝试在N时长获取锁,如果没有获取锁则直接失败
Condition newCondition()创建新的条件变量
方法含义
condition.await()等待这个条件
signal()唤醒
signalAll()唤醒全部

公平锁

默认不公平

通过构造方法实现

java
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /** Synchronizer providing all implementation mechanics */
    private final Sync sync;

    public ReentrantLock() {
        sync = new NonfairSync();
    }

    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

条件变量

synchronized中也有条件变量,就是我们讲原理时那个waitSet休息室,当条件不满足时进入waitSet等待

ReentrantLock的条件变量会吧waitSet进行细分,存在多个waitSet

  • await前需要获得锁
  • await执行后,会释放锁,进入conditionObject等待
  • await的线程被唤醒、打断、超时,重新竞争lock锁
  • 竞争lock锁成功后,从await后继续执行
java
static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
    Condition condition = lock.newCondition();
    Condition condition1 = lock.newCondition();
    lock.lock();
    try {
        condition.await();
        condition1.signal();
        
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}