ReentrantLock是一个互斥锁,它具有synchronized相同的能力;但相比之下,ReentrantLock扩展性更强,比如实现了公平锁。

下面详细拆解下ReentrantLock的公平锁和非公平锁的实现。

JDK版本:1.8.0_40

公平锁

先看ReentrantLock两个构造方法:


// 默认非公平
public ReentrantLock() {
  sync = new NonfairSync();
}

// 根据传参来实现公平或非公平锁
public ReentrantLock(boolean fair) {
	sync = fair ? new FairSync() : new NonfairSync();
}

因此,要想实现公平锁,只需要传参为true即可。

先来看一个测试类,后面都将围绕该测试类来分享:

public class TestReentrantLock {
    private static ReentrantLock lock = new ReentrantLock(true);
    
    public static void main(String[] args) {
        Runnable runnable = () -> {
            process();
        };

        Thread t0 = new Thread(runnable);
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);

        t0.start();
        t1.start();
        t2.start();
    }

    public static void process() {
        String name = Thread.currentThread().getName();
        System.out.println(name +" 尝试获取锁");
        lock.lock();
        try {
            System.out.println(name +" 已获取锁");
            sleep(1000L);
        } finally {
            System.out.println(name +" 释放锁");
            lock.unlock();
        }
    }

    private static void sleep(Long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            // ignore
        }
    }
}

输出:


Thread-0 尝试获取锁
Thread-2 尝试获取锁
Thread-1 尝试获取锁
Thread-0 已获取锁
Thread-0 释放锁
Thread-2 已获取锁
Thread-2 释放锁
Thread-1 已获取锁
Thread-1 释放锁

根据这个测试类,通过画图的方式,一起来看看每一步都执行了什么。

lock()过程

先来看看lock()过程

1)首先创建一个公平锁,ReentrantLock lock = new ReentrantLock(true);

image.png

2)t0 尝试获取锁,lock.lock(),该方法会调用父类的 acquire 方法