ReentrantLock

本文详细介绍了ReentrantLock相对于synchronized的特性,包括可重入、线程等待可中断、可设置超时时间、公平锁以及条件变量的使用。通过示例代码展示了如何实现线程中断和锁超时,并解释了ReentrantLock如何通过条件变量提供更灵活的等待和唤醒机制。同时,文中强调了synchronized不具备的中断和超时功能。
摘要由CSDN通过智能技术生成

相对于synchronized 具备以下特点:

  1. 可重入(synchronized也可重入
  2. 由其方法控制锁的开启和释放
  3. 线程等待可中断(lock.lockInterruptibly():拿不到锁就跳过,不进入阻塞态)
  4. 可设置超时时间(lock.tryLock():拿不到锁返回false,也不会进入阻塞态)
  5. 可设置为公平锁
  6. 支持多个条件变量(con1.await();con1.singal();con1.singalAll(),可以精准)

语法:

reentrantLock.lock()

try {
    //临界区
} finally {
    //释放锁
    reentrantLock.unlock();
}

可重入:

        是指同一个线程如果哦首次获得了这把锁,那么以为他是这把锁的拥有者,因此有权利再次获得这把锁。synchronized 和 reentrantLock 均可重入

线程等待可打断:

如果别的线程持有锁资源,当前线程会一直等待,无法被充分利用,因此要加上可打断的功能

【注:】上锁时要用 lock.lockInterruptibly(),因为lock.lock() 不支持打断

public class Test{
    private static ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args){
        Thread t1 = new Thread(()->{
            try{
                //如果此时该锁未被占用,就会获取该锁
                //如果此时该锁被占用,就会进入阻塞队列,不会一直等待
                System.out.println("尝试获得锁");
                lock.lockInterruptibly();
                System.out.println("已经获得锁");
            }
            catch (InterruptedException e){
                e.printStackTrace()
            }
        },"t1");
        
        t1.start();
        
    }
}

 返回结果:

尝试获得锁

已经获得锁

-------------------------

t1线程获得锁,正常结束

public class Test{
    private static ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args){
        Thread t1 = new Thread(()->{
            try{
                //如果此时该锁未被占用,就会获取该锁
                //如果此时该锁被占用,就会进入阻塞队列,不会一直等待
                System.out.println("尝试获得锁");
                lock.lockInterruptibly();
   
            }
            catch (InterruptedException e){
                e.printStackTrace()
                System.out.println("无法获得锁");
                return ;
            }
            
        },"t1");
        
        //主线程先获得锁
        lock.lock()
        //再开t1线程
        t1.start();
        
        
    }
}

 返回结果:

尝试获得锁

-------------------------

t1线程未打断,一直等待

public class Test{
    private static ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args){
        Thread t1 = new Thread(()->{
            try{
                //如果此时该锁未被占用,就会获取该锁
                //如果此时该锁被占用,就会进入阻塞队列,不会一直等待
                System.out.println("尝试获得锁");
                lock.lockInterruptibly();
   
            }
            catch (InterruptedException e){
                e.printStackTrace()
                System.out.println("无法获得锁");
                return ;
            }
            
        },"t1");
        
        //主线程先获得锁
        lock.lock()
        //再开t1线程
        t1.start();
        //睡眠后打断
        sleep(2);
        t1.interrupt();
        
    }
}

 返回结果:

尝试获得锁

无法获得锁

-------------------------

先尝试获得锁,2s后,主线程对t1线程执行了interrupt(),t1打断标记置为true,一直等待的t1线程被打断,在异常处理时将其结束

【注:】再次提醒 synchronized 和 lock.lock() 的等待无法打断

【Java并发】synchronized不可以被中断?_runhua的博客-CSDN博客_synchronized可以被中断吗

锁超时:

lock.tryLock() 如果获得锁返回 true,如果没有拿到锁立刻返回false

lock.tryLock(time) 如果获得锁返回 true,如果等待时间内活得锁返回 true,如果超时还在等待返回 false

优点:

可以化解线程因拿不到锁而陷入死锁的问题——哲学家就餐问题

可设置为公平锁:

ReentrantLock 默认构造器创建的是非公平锁机制,可以通过 new ReentrantLock(true) 创建公平锁,但是公平锁一般不会用到,因为公平锁会降低并发性能

条件变量:

条件变量就是Monitor里的waitSet变量,执行了wait() 的线程会进入该变量等待,这个变量就是条件变量

相较于synchronized,reentrantLock 拥有了创建Monitor的能力,因此一个reentrantLock对象可以创建多个Monitor对象,实现语法:

Condition con1 = reentrantLock.newCondition()
Condition con2 = reentrantLock.newCondition()

如此一个reentrantLock对象可以管理多个Monitor,也就是可以管理多个条件变量,灵活了等待、唤醒机制

等待:

con1.await()

con2.await()

唤醒:

con1.singal() 、con1.singalAll()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值