1 ReentrantLock简介
Since Java1.5大师Doug Lea的作品,实现了与synchronized相同的独占、可重入的功能。它是一个有趣并且类比于synchronized功能更为丰富的锁。
2 ReentrantLock与synchronized异同
| 功能列表 | ReentrantLock | synchronized |
|---|---|---|
| 是否可重入 | Yes | Yes |
| 是否独占 | Yes | Yes |
| 是否支持公平模式 | Yes | No |
| 支持唤醒指定线程 | Yes | No |
| 阻塞时可响应中断 | Yes | No |
| 获取锁时限时等待 | Yes | No |
支持公平模式、支持唤醒指定线程、阻塞时可响应中断、获取锁时限时等待是ReentrantLock类比于synchronized新增的功能。
3 ReentrantLock特性
ReentrantLock是由(AbstractQueuedSynchronizer类)AQS框架实现的,其本质上是一个队列(著名的CLH队列)。
现有5个线程尝试获取锁。分别是Thread0、Thread1、Thread2、Thread3、Thread4。Thread0获取到了锁。其他线程依照时间顺序进入CLH等待队列中。
3.1 非公平锁

值得注意的是Thread0释放锁之后,CLH队列(头元素的下一个元素)的Thread1出队并且获取了锁。
3.2 公平锁
公平锁与非公平锁基本不同之处在于公平锁是完全公平的,非公共锁是相对公平但做不到完全公平。
举个例子:
上述中5个线程已经就位,Thread0已经获取锁并且始终未释放,其他线程已经进入CLH队列。
此时新创建一个线程Thread5尝试获取锁。
非公平锁 : Thread5有获取锁的优先权,Thread5先尝试获取锁。如果未获取到加入CLH队列尾部。
公平锁: Thread5没有先获取锁的优先权。直接加入到CLH队列尾部等待。
例子非公平锁

例子公平锁

3.3 Condition条件等待
同上例子,现有5个线程尝试获取锁。分别是Thread1、Thread2、Thread3、Thread4。
| 图片N | 过程说明 |
|---|---|
| 1 | Thread1获取到了锁。其他线程依照时间顺序进入CLH等待队列中 |
| 2 | Thread1调用Condtion#await()进入等待队列并释放锁 |
| 3 | 新创建一个线程Thread5并且在与CLH队列争抢锁是获得了锁(非公平锁特有)。之后调用Condtion#await()进入等待队列并释放锁 |
| 4 | CLH队列争抢锁,Thread2出队并获得锁 |
| 5 | Thread2出队后,CLH队列头节点被丢弃,Thread2原节点变为头节点(此时该节点已经不在保存Thread2) |
| 6 | 调用Condtion#signal()该condition队列首元素出队并移动(transfer)到CLH队尾等待获取锁。 |

3.4 其他特性
参考文章 www.cnblogs.com/takumicx/p/…
4 结语
本文只是本人浅薄学习见解,如有问题,请立即指出。关于并发后续还会探讨读写锁、线程池等实现。希望这篇文章能够帮助大家了解显示锁。
参考文章
ReentrantLock(重入锁)功能详解和应用演示 www.cnblogs.com/takumicx/p/…
从源码角度彻底理解ReentrantLock(重入锁) www.cnblogs.com/takumicx/p/…