显式锁之ReentrantLock实现

  下图是Lock接口清单,定义了一些抽象的锁操作。Java本身提供了内部锁机制,那么还需要显示Lock,何用?与内部加锁机制不同,Lock提供了无条件、可轮询、定时、可中断的锁获取操作;所有加锁和解锁的操作都是显式的。既然是锁,那么Lock的实现必须提供具有与内部加锁相同内存可见性语义,同时语义、调度算法、顺序保证、性能特性这些可以不同——即功能可以更强大,但是基本核心底层功能不能丢失。

    显式锁之ReentrantLock实现显式锁之ReentrantLock实现

   ReentrantLock实现了Lock接口,那么看看这个接口实现是如何在保证内部锁功能同时显式调用的。通常调用范式如下:

    显式锁之ReentrantLock实现

  譬如CyclicBarrier中的实现:

    显式锁之ReentrantLock实现

   阅读ReentrantLock源码可知其实现使用了AQS:

    显式锁之ReentrantLock实现

  ReentrantLock只支持独占的获取操作,因此它实现了AQS中的tryAcquire/tryRelease和isHeldExclusively:

    显式锁之ReentrantLock实现非公平版

     显式锁之ReentrantLock实现

   通过源码可知ReentrantLock使用同步状态持有锁获取操作的计数,同时还维护了一个owner变量来持有当前拥有的线程标识符。只有在当期线程刚刚获取到锁,或者刚刚释放了锁的时候,才会修改owner。在tryRelease中,检查owner域以确保当期线程在执行一个unlock操作之前已经拥有了锁;在tryAcquire中,使用这个域来区分重进入的获取操作尝试与竞争的获取操作尝试:

    显式锁之ReentrantLock实现显式锁之ReentrantLock实现

   当一个线程尝试去获取锁时,tryAcquire会首先请求锁的状态。如果锁未被占有尝试更新锁的状态,表明锁已被占有。因为状态可能在被观察后的几条指令中被修改了,所以tryAcquire使用compareAndSetState来尝试原子地更新状态表明这个锁现在已经被占有,并确保状态自最后一次观察后没有被修改过。假设锁状态表明它已经被占有,如果当前线程是锁的拥有者,那么获取计数会递减;如果当前线程不是锁的拥有者,那么获取操作的阐述会失败。

 

 

 

 

 

 

 

  

 

上一篇:什么是可重入锁


下一篇:MySQL学习笔记之事务