摘要
从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些。
场景1:如果发现该操作已经在执行中则不再执行(有状态执行)
a、用在定时任务时,如果任务执行时间可能超过下次计划执行时间,确保该有状态任务只有一个正在执行,忽略重复触发。
b、用在界面交互时点击执行较长时间请求操作时,防止多次点击导致后台重复执行(忽略重复触发)。
以上两种情况多用于进行非重要任务防止重复执行,(如:清除无用临时文件,检查某些资源的可用性,数据备份操作等)
1 |
private ReentrantLock lock = new ReentrantLock();
|
01 |
if (lock.tryLock()) { //如果已经被lock,则立即返回false不会等待,达到忽略操作的效果
|
02 |
03 |
try {
|
04 |
05 |
//操作
|
06 |
07 |
} finally {
|
08 |
lock.unlock();
|
09 |
}
|
10 |
11 |
}
|
场景2:如果发现该操作已经在执行,等待一个一个执行(同步执行,类似synchronized)
这种比较常见大家也都在用,主要是防止资源使用冲突,保证同一时间内只有一个操作可以使用该资源。
但与synchronized的明显区别是性能优势(伴随jvm的优化这个差距在减小)。同时Lock有更灵活的锁定方式,公平锁与不公平锁,而synchronized永远是公平的。
这种情况主要用于对资源的争抢(如:文件操作,同步消息发送,有状态的操作等)
ReentrantLock默认情况下为不公平锁
1 |
private ReentrantLock lock = new ReentrantLock(); //参数默认false,不公平锁
|
2 |
private ReentrantLock lock = new ReentrantLock( true ); //公平锁
|
1 |
try {
|
2 |
lock.lock(); //如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
|
3 |
4 |
//操作
|
5 |
6 |
} finally {
|
7 |
lock.unlock();
|
8 |
} |
不公平锁与公平锁的区别:
公平情况下,操作会排一个队按顺序执行,来保证执行顺序。(会消耗更多的时间来排队)
不公平情况下,是无序状态允许插队,jvm会自动计算如何处理更快速来调度插队。(如果不关心顺序,这个速度会更快)
场景3:如果发现该操作已经在执行,则尝试等待一段时间,等待超时则不执行(尝试等待执行)
这种其实属于场景2的改进,等待获得锁的操作有一个时间的限制,如果超时则放弃执行。
用来防止由于资源处理不当长时间占用导致死锁情况(大家都在等待资源,导致线程队列溢出)。
01 |
try {
|
02 |
if (lock.tryLock( 5 , TimeUnit.SECONDS)) { //如果已经被lock,尝试等待5s,看是否可以获得锁,如果5s后仍然无法获得锁则返回false继续执行
|
03 |
04 |
05 |
try {
|
06 |
07 |
08 |
//操作
|
09 |
10 |
11 |
} finally {
|
12 |
lock.unlock();
|
13 |
}
|
14 |
15 |
16 |
}
|
17 |
} catch (InterruptedException e) {
|
18 |
e.printStackTrace(); //当前线程被中断时(interrupt),会抛InterruptedException
|
19 |
}
|
20 |
21 |
|
22 |
|
23 |
<div>
|
24 |
25 |
26 |
|
27 |
|
28 |
</div>
|
29 |
<span></span> |
场景4:如果发现该操作已经在执行,等待执行。这时可中断正在进行的操作立刻释放锁继续下一操作。
synchronized与Lock在默认情况下是不会响应中断(interrupt)操作,会继续执行完。lockInterruptibly()提供了可中断锁来解决此问题。(场景2的另一种改进,没有超时,只能等待中断或执行完毕)
这种情况主要用于取消某些操作对资源的占用。如:(取消正在同步运行的操作,来防止不正常操作长时间占用造成的阻塞)
1 |
try {
|
2 |
lock.lockInterruptibly();
|
3 |
//操作
|
4 |
5 |
} catch (InterruptedException e) {
|
6 |
e.printStackTrace();
|
7 |
} finally {
|
8 |
lock.unlock();
|
9 |
} |
可重入概念
若一个程序或子程序可以“安全的被并行执行(Parallel computing)”,则称其为可重入(reentrant或re-entrant)的。即当该子程序正在运行时,可以再次进入并执行它(并行执行时,个别的执行结果,都符合设计时的预期)。可重入概念是在单线程操作系统的时代提出的。
相关推荐
Java可重入锁的实现原理与应用场景 Java可重入锁是一种特殊的锁机制,允许同一个线程在不同的层次上获取同一个锁,而不会发生死锁或阻塞的情况。这种锁机制广泛应用于多线程编程中,用于解决线程之间的同步问题。 ...
ReentrantLock,可重入锁,是Java并发编程中一个重要的锁实现,它提供了比synchronized更高级别的控制能力,包括公平性和非公平性选择。本文将深入探讨ReentrantLock的原理,特别是其公平锁与非公平锁的概念,以及...
ReentrantLock是一个可重入锁,在ConcurrentHashMap中使用了ReentrantLock。它是一个可重入的排他锁,它和synchronized的方法和代码有着相同的行为和语义,但有更多的功能。 ReentrantLock是被最后一个成功lock锁...
ReentrantLock支持重入性,意味着一个线程可以多次进入同一段被该锁保护的代码,只要这个线程还没有释放这个锁。这种特性对于某些复杂并发场景特别有用。 在ReentrantLock中,重入性是通过维护每个锁的同步状态(即...
在Java中,ReentrantLock是内置的可重入锁,而在分布式环境中,我们可以利用Redis的特性来构建类似的机制。 Redis提供了`SETNX`(Set if Not eXists)命令,可以用于原子性地设置一个键的值,如果键不存在的话。这...
4. **可重入锁**:可重入锁允许一个线程获取同一资源的多次锁定,如Java的`synchronized`和`ReentrantLock`。这样可以避免死锁,当一个线程已经持有锁,尝试获取同一锁时,它能再次获得。 5. **互斥锁(Mutex)**:...
Lock、Synchronized 和 ReentrantLock 是 Java 中三种常用的同步机制,每种机制都有其特点和使用场景。下面对这三种机制进行详细的分析和比较。 一、Synchronized Synchronized 是 Java 中最基本的同步机制,它...
ReentrantLock 的实现原理基于 AQS(AbstractQueuedSynchronizer),是一个重入锁,允许一个线程反复地获取锁而不会出现自己阻塞自己的情况。 ReentrantLock 的构造方法可以指定锁的类型,包括公平锁和非公平锁。...
相比之下,ReentrantLock(可重入锁)是Java并发包java.util.concurrent.locks中的一个类,提供了更细粒度的锁控制。ReentrantLock允许显式获取和释放锁,并且支持更丰富的锁原语,如公平锁、非公平锁、可中断锁、...
相较于`synchronized`,`ReentrantLock`的主要优势在于其灵活性、可重入性和可中断性。 1. **可重入性**: 无论是`synchronized`还是`ReentrantLock`,都支持可重入特性。这意味着一个线程可以多次获取同一锁,...
在Java多线程高并发编程中,重入锁(ReentrantLock)是一个至关重要的概念,它提供了比Java内置锁(synchronized)更细粒度的控制,并且具有更高的可读性和可扩展性。本篇文章将深入探讨重入锁的相关知识点。 首先...
ReentrantLock的主要特点是可以重入,即一个线程可以多次获得锁,而不需要释放锁。这种机制可以避免死锁的出现。 ReentrantLock的使用场景非常广泛,一般用于解决多线程访问共享资源的问题。在Java中,...
ReentrantLock是一个可重入的锁,这意味着一个线程可以多次获取同一锁,这与synchronized内置锁的行为相同。然而,与内置锁不同的是,使用ReentrantLock需要显式调用`lock()`和`unlock()`方法来获取和释放锁,这增加...
在Java并发编程中,`ReentrantLock`是一个可重入的互斥锁,相比`synchronized`提供了更细粒度的控制以及更丰富的特性。`ReentrantLock`的公平性和非公平性是其重要的特性之一。在上述代码中,我们创建了一个`...
可重入锁,如`java.util.concurrent.locks.ReentrantLock`,允许一个线程多次进入同一锁定区域,这在递归方法中尤其有用。当线程试图重新进入已被其持有的锁时,它不会被阻塞。这与传统的非可重入锁形成对比,后者...
Java中的`ReentrantLock`是Java并发包`java.util.concurrent.locks`中的一个高级锁机制,它是可重入的互斥锁,具有与`synchronized`关键字相似的同步性,但提供了更多的灵活性和控制功能。本篇文章将深入探讨`...
ReentrantLock的名字来源于它的可重入性,这意味着一个线程可以多次获取同一把锁,这在递归调用中特别有用。无论是ReentrantLock还是synchronized,它们都是可重入锁。 ReentrantLock在Java 5.0引入,最初因其性能...
ReentrantLock是由Java提供的可重入互斥锁,支持公平锁和非公平锁两种模式。非公平锁的特性是获取锁的线程不论先后,都有机会获得锁,而公平锁则遵循先进先出的原则,保证线程按照请求锁的顺序进行。 2. **...
- 它是可重入的,即一个线程可以多次获取同一锁,不会发生死锁。 2. **使用方式**: - `ReentrantLock`提供`lock()`和`unlock()`方法来加锁和解锁。 - 支持公平锁(通过构造函数传入`true`)和非公平锁(默认)...
- 是,则将锁的重入次数加1,并返回true。 - 否,则返回false。 #### 总结 ReentrantLock通过AQS提供了强大的锁管理能力,尤其在非公平锁模式下,即使在高并发场景下也能表现出良好的性能。通过对上述流程的分析...