ReentrentLock是什么?该如何实现?

TheDisguiser 2020-05-07 17:23:34 java常见问答 8919

今天要给大家介绍的是ReentrentLock这样一个功能,包括介绍它的概念与实现方式,一起来看看吧。

ReentrantLock基本概念

ReentrantLock是一个可重入锁,它也叫做递归锁,指的是同一线程中外层函数获得锁之后 ,内层递归函数依然可以获取该锁的代码,不会受外层函数的影响。

在JAVA中ReentrantLock 和synchronized 都是可重入锁;

重入锁ReentrantLock 相对来说是synchronized、Object.wait()和Object.notify()方法的替代品或者说是增强版,在JDK5.0的早期版本,重入锁的性能远远好于synchronized,但从JDK6.0开始,JDK在synchronized上做了大量的优化,使得两者的性能差距并不大。但ReentrantLock也有一些synchronized没法实现的特性。

ReentrantLock 在Java中是一个基础的锁,ReentrantLock 会实现Lock接口从而提供一系列基础函数,程序员可以十分灵活的应用函数满足各种复杂多变应用场景;

ReentrantLock实现

Lock接口:

   //获取锁,获取不到lock就不罢休,不可被打断,即使当前线程被中断,线程也一直阻塞,直到拿到锁, 比较无赖的做法。
   void lock();
   /**
    *获取锁,可中断,如果获取锁之前当前线程被interrupt了,
    *获取锁之后会抛出InterruptedException,并且停止当前线程;
    *优先响应中断
    */
   void lockInterruptibly() throws InterruptedException;
   //立即返回结果;尝试获得锁,如果获得锁立即返回ture,失败立即返回false
   boolean tryLock();
   //尝试拿锁,可设置超时时间,超时返回false,即过时不候
   boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
   //释放锁
   void unlock();
   //返回当前线程的Condition ,可多次调用
   Condition newCondition();

ReentrantLock 实现了Java中锁的核心接口Lock,在Lock接口中定义了标准函数,但实际上它的具体实现是在实体类中的。

私有public方法

//传入boolean值,true时create一个公平锁,false为非公平锁
ReentrantLock(boolean fair)
//查看有多少线程等待锁
int getQueueLength()
//是否有线程等待抢锁
boolean hasQueuedThreads()
//是否有指定线程等待抢锁
boolean hasQueuedThread(Thread thread)
//当前线程是否抢到锁。返回0代表没有
int getHoldCount()
//查询此锁是否由任何线程持有
boolean isLocked()
//是否为公平锁
boolean isFair()

ReentrantLock除了实现Lock定义的一些标准函数外,还同时提供其他的用于管理锁的public方法:

Condition的应用

ReentrantLock中另一个重要应用就是Condition,Condition是Lock的一个条件,可以多次newCondition()获得多个条件,Condition一般用于多线程之间通信,通过Condition能够更加精细的控制多线程的休眠与唤醒,且它在粒度和性能上都会优于Object的各种通信方法。

Condition 源码:

public interface Condition
{
    /**
     *Condition线程进入阻塞状态,调用signal()或者signalAll()再次唤醒,
     *允许中断如果在阻塞时锁持有线程中断,会抛出异常;
     *重要一点是:在当前持有Lock的线程中,当外部调用会await()后,ReentrantLock就允许其他线程来抢夺锁当前锁,
     *注意:通过创建Condition对象来使线程wait,必须先执行lock.lock方法获得锁
     */
    void await () throws InterruptedException;
    //Condition线程进入阻塞状态,调用signal()或者signalAll()再次唤醒,不允许中断,如果在阻塞时锁持有线程中断,继续等待唤醒
    void awaitUninterruptibly();
    //设置阻塞时间,超时继续,超时时间单位为纳秒,其他同await();返回时间大于零,表示是被唤醒,等待时间并且可以作为等待时间期望值,小于零表示超时
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    //类似awaitNanos(long nanosTimeout);返回值:被唤醒true,超时false
    boolean await (long time, TimeUnit unit) throws InterruptedException;
    //类似await(long time, TimeUnit unit) 
    boolean awaitUntil(Date deadline) throws InterruptedException;
    //唤醒指定线程
    void signal();
    //唤醒全部线程
    void signalAll();
}

ReentrantLock.Condition的线程通信:

ReentrantLock.Condition是一种在粒度和性能上都完全优于Object的notify()、wait()、notifyAll()线程通信的方式。

Condition通信方法相对于Object通信,在粒度上更加细化,表现在一个Lock对象上引入多个Condition监视器、通信方法中除了和Object对应的三个基本函数外,更是新增了线程中断、阻塞超时的函数;

以上就是本文的所有内容了,想了解更多java常见问答知识请关注奇Q工具网吧。