锁——3、Reentrantlock

一、ReenTrantLock是可重入锁
可重入锁的特点
可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。
谁等的时间最长,谁就先获取锁

ReenTrantLock的特点:
1.ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。
2.ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。
3.ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。

应用场景:需要使用以上三个特点时,使用ReenTrantLock。

二、与synchronized的区别
见前一篇

三、ReenTranLock解决死锁的方式:

1、响应中断

通过lock.lockInterruptibly()方法来实现。对于synchronized来说,对于一个线程在等待锁。那么只有两种情况,要么获得锁,要么保持等待。重入锁提供另一种可能中断,如果一个线程在等待锁,如果它收到一个通知,被告知无需再等待,可以停止工作了。这种情况对于处理死锁是有帮助的

2、锁申请等待限时

通过lock.tryLock()方法来实现。如果其他线程占有锁,则当前线程不会等待,立即返回false。tryLock(long ,TimeUnit),tryLock方法既可以接受无参调用,还可以接受参数,第一个参数等待时长,第二个表示计时单位。如果超过等待时长还没有获取到锁,会停止等待并返回false。

四、tryLock和lock和lockInterruptibly三个方法的区别

(1)tryLock仅在其他线程未保持锁时,才获取锁,并立即返回true。

如果锁已经被其他线程保持,就立即返回false。tryLock(long timeout,TimeUnit unit),可以增加时间限制,如果超过该时间段还没获得锁,返回false。

(2)lock能获得锁就返回true,不能的话一直等待获得锁

(3)lock和lockInterruptibly,如果两个线程分别执行这两个方法,但此时中断这两个线程,前者不会抛出异常,而后者会抛出异常InterruptedException。lockInterruptibly方法在其他线程在中断当前线程时,在抛出异常的同时,会停止等待获取锁。

五、Condition的使用

  • 使用ReentrantLock类的newCondition()方法可以获取Condition对象

  • 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法

  • 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了

Lock接口:Lock接口的出现代替了同步代码块和同步函数。将同步的隐式锁操作变成了显示锁操作,同时也变得更加灵活。一个锁可以加上多组监视器。

Lock接口中的一些方法:lock()//获取锁,unlock()//释放锁通常需要定义在finally代码块中。

Condition接口:此接口中封装了awiat(),signal(),signalAll(),方法。代替了原来锁中的wait(),notify(),notifyAll()监视器方法

六、Concurrent包中的reentrantlock有用过吗
场景1:如果发现该操作已经在执行中则不再执行(有状态执行)

a、用在定时任务时,如果任务执行时间可能超过下次计划执行时间,确保该有状态任务只有一个正在执行,忽略重复触发。
b、用在界面交互时点击执行较长时间请求操作时,防止多次点击导致后台重复执行(忽略重复触发)。

posted on 2021-09-16 10:20  夜萤火虫和你  阅读(199)  评论(0编辑  收藏  举报

导航