reentrantlock一般使用场景是什么小伙伴们知道吗?了解这个也是有必要的,说不定什么时候就会用到reentrantlock,下面一起瞧瞧吧。
1、发现已经执行的一个操作,等待逐个执行
这是种较常见的场景,主要是为了防止资源使用冲突,保证在一个时间内只有一个操作进行。
但,有个问题,它与synchronized有个明显区别,性能优势,虽然随着JVM优化差距逐渐减小。但Lock也有更灵活的锁定方式,如公平锁和不公平锁,而synchronized永远是公平的。ReentrantLock默认为不公平锁。
private ReentrantLock lock = new ReentrantLock(); //参数默认false,不公平锁 private ReentrantLock lock = new ReentrantLock(true); //公平锁
try { lock.lock(); //如果被其它资源锁定,会在此等待锁释放,达到暂停的效果 //操作 } finally { lock.unlock(); }
公平锁与不公平锁间区别:
公平锁下,操作会排一个队按顺序执行,来保证执行顺序。(但会消耗更多的时间来排队)
不公平情况下,是无序状态的并且允许插队,jvm会自动计算如何处理更快速来调度插队。(如果不关心顺序的话,这个速度会更快)
2、发现正在执行的一个,尝试等待一段时间,如超时则不执行
这种场景中等待获得锁的操作是有一个时间的限制的,如果超时就一定放弃执行,否则就死锁了。
一般用来防止由于资源处理不当导致长时间占用导致死锁情况(大家都在等待资源,导致线程队列溢出)。
try { if (lock.tryLock(5, TimeUnit.SECONDS)) { //如果已经被lock,尝试等待5s,看是否可以获得锁,如果5s后仍然无法获得锁则返回false继续执行 try { //操作 } finally { lock.unlock(); } } } catch (InterruptedException e) { e.printStackTrace(); //当前线程被中断时(interrupt),会抛InterruptedException }
3、如若发现一个操作已经在执行中则不再执行
a、定时任务在执行时,如果发现任务执行时间可能超过下次计划执行时间,确保该有状态任务只有一个正在执行,忽略重复触发。
b、用在界面交互时点击执行较长时间请求操作时,防止多次点击导致后台重复执行,忽略重复触发。
private ReentrantLock lock = new ReentrantLock();
if (lock.tryLock()) { //如果已经被lock,则立即返回false不会等待,达到忽略操作的效果 try { //操作 } finally { lock.unlock(); } }
4、如若一个操作正在执行,等待执行。但同时可中断正在进行的操作立刻释放锁继续下个操作。
正常情况下,synchronized与Lock在默认情况是不会响应中断(interrupt)操作的,它会一直执行直到完成任务。lockInterruptibly()提供了可中断锁来解决此问题。
这种情况主要用于取消某些操作对资源的占用。如:取消正在同步运行的操作,来防止不正常操作长时间占用造成的阻塞等。
try { lock.lockInterruptibly(); //操作 } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); }
以上就是本篇文章的所有内容,一般的java编程问题相信小伙伴们已经能直接解决了,更多java常见问题及解决方法可以关注我们了解具体。
推荐阅读: