J.U.C之AQS-ReentrantLock

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34203492/article/details/82629150

简单说一下 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

猜你喜欢

转载自blog.csdn.net/qq_34203492/article/details/82629150