java reentrantlock怎么使用?概念和使用详解

KLQ 2020-08-04 11:16:06 java常见问答 3862

下面的文章内容要给大家介绍的就是java当中的reentrantlock,主要介绍了reentrantlock的概念以及适用,一起来了解一下吧。

reentrantlock概念和使用

可重入锁也被叫做递归锁,指的是同一线程外层函数获得锁之后 ,内层递归函数仍然有获取这个锁的代码,但不受影响,在JAVA当中,ReentrantLock以及synchronized都是可重入锁。

ReentrantLock在Java也是一个基础的锁,ReentrantLock实现Lock接口提供一系列的基础函数,开发人员可以灵活的是应用函数满足各种复杂多变应用场景。

(1)Lock接口:

Java中的ReentrantLock也是实现了Java中锁的核心接口Lock。

在Lock接口定义了标准函数,可是,具体实现是在实体类中[类似listarrayListlinkedList关系]。

 //获取锁,获取不到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();

(2)ReentrantLock私有public方法(ReentrantLock中除了实现Lock中定义的一些标准函数外,同时提供其他的用于管理锁的public方法)。

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

(3)ReentrantLock中Condition的使用

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

还是先来看一下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对应的三个基本函数外,更是新增了线程中断、阻塞超时的函数;

Condition中通信方法相对Object的通信在性能上更高效,性能的优化表现在ReentrantLock比较synchronized的优化 ;

基本示例代码:

多线程通信/同步的一个经典的应用属于**生产者消费者模式**,关于通过ReentrantLock的newCondition()是实现生产者消费者模式可以直接参考: 生产者消费者模式 ;

ReentrantLock.Condition线程通信注意点:

1.使用**ReentrantLock.Condition的signal()、await()、signalAll()方法使用之前必须要先进行lock()操作**[记得unlock()],类似使用Object的notify()、wait()、notifyAll()之前必须要对Object对象进行synchronized操作;否则就会抛IllegalMonitorStateException;

2.注意在使用**ReentrantLock.Condition中使用signal()、await()、signalAll()方法,不能和Object的notify()、wait()、notifyAll()方法混用,否则抛出IllegalMonitorStateException`;

对于reentrantlock你还有什么不了解的吗?请继续通过奇Q工具网的常见问题栏目来了解吧,有更多java常见问题及解决方法可以为你分享解答。

推荐阅读:

Synchronized和Reentrantlock区别是什么?简单叙述

sychronized和reentrantlock区别在哪里?都有什么用处?

ReentrantLock属于乐观锁还是悲观锁?