浅析重入锁ReentrantLock

285 阅读2分钟

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/…