JUC工具包:01.ReentrantLock

基本概念

synchronized是Java的内置锁,synchronized加锁和释放锁由jvm控制,不需要人为控制,所以使用的时候非常简单,但synchronized锁也存在许多的缺点。
1.不够灵活,不能跨方法加锁
2.当线程尝试获取synchronized锁的时候,如果获取不到锁会一直阻塞,这个阻塞的过程,用户无法控制

Reentrantlock是java.util.concurrent包下的可重入锁,可中断锁,默认是非公平锁。它的获取锁与释放锁由人手动控制,并且提供了更加细粒度的加锁方法,弥补了一些synchronized加锁方式的缺点。

基本使用

ReentrantLock lock = new ReentrantLock();//创建锁
lock.lock();//加锁
try{
  //逻辑代码
}finally{
  lock.unlock();//释放锁
  //释放锁的操作一定要放在finally中,否则,程序出现了异常,锁没有释放,那么其他线程就再也没有机会获取这个锁了。
}


ReentrantLock是可重入锁

可重入锁:重入锁是指同一个线程可以多次获得同一把锁;ReentrantLock和关键字Synchronized都是可重入锁

ReentrantLock lock = new ReentrantLock();
lock.lock();
lock.lock();
try{
  //逻辑代码
}finally{
  lock.unlock();//释放锁
  lock.unlock();
}

注意:

1. lock()方法和unlock()方法需要成对出现,锁了几次,也要释放几次,否则后面的线程无法获取锁了;可以将add中的unlock删除一个事实,上面代码运行将无法结束

2. unlock()方法放在finally中执行,保证不管程序是否有异常,锁必定会释放

ReentrantLock实现公平锁

看一下jdk中ReentrantLock的源码,2个构造方法:

public ReentrantLock(){
 sync = new NonfairSync();
}
public ReentrantLock(boolean fair){
 sync = fair ?new FairSync():new NonfairSync();
}

默认构造方法创建的是非公平锁。第2个构造方法,有个fair参数,当fair为true的时候创建的是公平锁.

//公平锁
ReetrantLock lock = new ReetrantLock(true);

ReentrantLock获取锁的过程是可中断的

如果需要在获取锁的过程中能够中断,需要使用ReentrantLock的lockInterruptibly()获取锁,当前线程获取锁之后,在调用线程的interrupt()方法,将中断标准变为ture后,就会引发InterruptedException异常。

ReentrantLoca lock = new ReentrantLock();
Thread t = new Thread(()->{
  try{
    lock.lockInterruptibly();//获取锁
    //逻辑代码
  }catch(InterruptedException e){
    System.out.println("中断标志"+this.isInterrupted());
    e.printStackTrace();
  }finally{
    if(lock.isHeldByCurrentThread){//当前线程是否获取了锁
      lock.unlock();
    }
  }
});
t.start();
t.interrupt();

线程调用interrupt()之后,线程的中断标志会被置为true,触发InterruptedException异常之后,线程的中断标志有会被清空,即置为false,所以当线程调用interrupt()引发InterruptedException异常,中断标志的变化是:false->true->false

ReentrantLock锁申请等待限时

ReentrantLock提供了个tryLock(),可以选择传入时间参数,表示等待指定的时间,无参则表示立即返回锁申请的结果:true表示获取锁成功,false表示获取锁失败。

//tryLock无参
public boolean tryLock() //尝试去获取锁,没有获取到立即返回
//tryLock有参
public boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException
//获取锁超时时间设置为3秒,3秒内是否能否获取锁都会返回
lock.tryLock(3,TimeUnit.SECONDS)

有参的tryLock()方法,第一个参数是时间大小,第二个参数是是时间类型,是一个枚举,可以表示时、分、秒、毫秒等。

获取锁的4种方法对比

获取锁的方法是否立即响应(不会阻塞)是否响应中断
lock()××
lockInterruptibly()×
tryLock()×
tryLock(long timeout, TimeUnit unit)×
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值