ReentrantLock 源码解析
ReentrantLock
的核心是通过 AQS 实现的,具备了 AQS 的特征。
ReentrantLock 加锁过程
我们先说一下这例子: 以银行办理业务的案例来模拟我们的 AQS 是如何进行线程的管理和通知唤醒机制:
环境:有一个业务窗口 3 个排队的顾客;
类比(对号入座):3 个线程来模拟 3个排队的顾客,然后锁表示银行的窗口。
再来一个直观一点的示意图:
通过这个例子大家可以进行锁的调试和辅助理解,接下来我就以 ReentrantLock
中具体的方法来分析加锁、解锁过程。
代码例子:
// 以银行办理业务的案例来模拟我们的 AQS 是如何进行线程的管理和通知唤醒机制 // 3 个线程来模拟银行网点,受理窗口办理业务的顾客 // A 顾客就是第一个顾客,此时受理窗口没有任何人, A可以直接去办理 Lock lock = new ReentrantLock(); new Thread(() -> { lock.lock(); System.out.println(" -------> A Thread come in"); // 暂停几秒钟线程 try { TimeUnit.MINUTES.sleep(20); } catch (InterruptedException e) {e.printStackTrace();} lock.unlock(); }, "A").start(); // 第2个顾客,由于业务窗口只有一个(只能有一个线程持有锁),此时 B进行等待 // 进入候客区 new Thread(() -> { lock.lock(); System.out.println(" -------> B Thread come in"); try { TimeUnit.MINUTES.sleep(20); } catch (InterruptedException e) {e.printStackTrace();} lock.unlock(); }, "B").start(); // 第3个顾客,由于业务窗口只有一个(只能有一个线程持有锁),此时 C进行等待 // 进入候客区 new Thread(() -> { lock.lock(); System.out.println(" -------> C Thread come in"); try { TimeUnit.MINUTES.sleep(20); } catch (InterruptedException e) {e.printStackTrace();} lock.unlock(); }, "C").start();
ReentrantLock 核心方法
ReentrantLock
的方法和结构如下图所示,不得不说 Doug Lea
大神的水平还是非常高的,方法和命名上面其实都是见名知意的。还有就是这块公平锁(FairSync)、非公平锁(NonfairSync) 都是依赖 AbstractQueuedSynchronizer
这个模板方法实现的。
lock()
是加锁方法,默认为非公平锁。
构造方法如下所示:
lock 方法如下所示:
公平锁 lock 方法实现