简单说一下 ReentrantLock
简介:
ReentrantLock 是一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大。ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥有。当锁定没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁定并返回。如果当前线程已经拥有该锁定,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。
它提供了lock()方法:
如果该锁定没有被另一个线程保持,则获取该锁定并立即返回,将锁定的保持计数设置为 1。
如果当前线程已经保持该锁定,则将保持计数加 1,并且该方法立即返回。
如果该锁定被另一个线程保持,则出于线程调度的目的,禁用当前线程,并且在获得锁定之前,该线程将一直处于休眠状态,此时锁定保持计数被设置为 1。
ReentrantLock 一直和synchronized作比较,在《java并发编程实战》13.4节中讲:在一些内置锁(synchronized)无法满足的需求情况下,ReentrantLock可以作为一种高级工具。当需要一些高级功能时才应该使用ReentrantLock,这些功能包括:可定时的、可轮询的与可中断的锁获取操作,公平队列,以及非块结构的锁。否则,影视应该优先使用synchronized。
使用场景:
场景1:
if (lock.tryLock()) { //如果已经被lock,则立即返回false不会等待,达到忽略重复加锁操作的效果 比如:防止页面多次点击导致后台重复执行
try {
//do something....
} finally {
lock.unlock(); //释放锁
}
}
场景2:如果发现该操作已经在执行,则尝试等待一段时间,等待超时则不执行(尝试等待执行)
try {
if (lock.tryLock(2, TimeUnit.SECONDS)) { //如果已经被lock,尝试等待2s,看是否可以获得锁,如果2s后仍然无法获得锁则返回false
try {
//do something....
} finally {
lock.unlock(); //释放锁
}
}
} catch (InterruptedException e) {
e.printStackTrace(); //当前线程被中断时(interrupt),会抛InterruptedException
}
场景3:同步执行,类似synchronized
private static ReentrantLock lock = new ReentrantLock(); //参数默认false,不公平锁
private static ReentrantLock lock = new ReentrantLock(true); //公平锁
try {
lock.lock(); //如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
//do something.... 这里其实和synchronized效果类似 synchronized是公平锁 ReentrantLock可以用灵活的锁定方式,公平锁与不公平锁
} finally {
lock.unlock();
}
场景4:可中断锁
可以用来取消某些操作对资源的占用。如:(取消正在同步运行的操作,来防止不正常操作长时间占用造成的阻塞)
ReentrantLock.lockInterruptibly()
允许在等待时由其它线程调用等待线程的Thread.interrupt方法来中断等待线程的等待而直接返回,这时不用获取锁,而会抛出一个InterruptedException。 ReentrantLock.lock方法不允许Thread.interrupt中断,即使检测到Thread.isInterrupted,一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功后再把当前线程置为interrupted状态,然后再中断线程。
try {
lock.lockInterruptibly();
//do something....
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
场景5:独占可重入锁
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
for (int i = 1; i <= 3; i++) {
lock.lock(); //先获取锁3次
}
for(int i=1;i<=3;i++){
try {
//do something....
} finally {
lock.unlock(); //然后释放锁3次
}
}
}
ReentrantLock简单使用介绍完了
个人浅薄理解,欢迎补充
点击链接加入群聊【Java技术学习闲聊群】:https://jq.qq.com/?_wv=1027&k=59emCBA