认识ReentrantLock

ReentrantLock

在Java中通常使用锁有两种方式,一种是使用synchronized关键字,另一种就是Lock接口下的子类,ReentrantLock就是Lock的默认实现之一。ReentrantLock是可重入锁,也是独占锁。弥补synchronized的局限性,提供更加灵活的加锁方式。

1、常见方法
  • 获取锁
/** 获取锁 */
void lock();

/** 如果当前线程未被中断,则获取锁 */
void lockInterruptibly();

/** 仅在调用时锁为空闲状态才获取锁 */
boolean tryLock();

/** 如果锁在给定的等待时间内空闲,并且线程未被中断,则获取锁,弱国超过等待时间则获取锁失败,返回false */
boolean tryLock(long timeout, TimeUnit unit);
  • 释放锁
/** 释放锁 */
void unlock()

其中最常用的就是lock()和unlock(),使用lock时需要手动释放锁,一般用try…catch包住业务代码,在finally里释放锁。

	private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        lock.lock();
        try {
            System.out.println(".........");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
2、锁类型

ReentrantLock支持公平锁和非公平锁,默认的构造非公平锁(无参构造函数),而构造公平锁采用有参构造函数,传入Boolean类型的true 【new ReentrantLock(true)】。

  • 公平锁

    按照线程等待时间来排序,等待时间越久的先被执行。内部说白了就是一个链表(等待队列),每次释放锁后,从链表头部开始取。

  • 非公平锁

    非公平锁发生在对象A.unlock()同时,对象B里面想要获取锁,这时候对象A还没有通知等待队列中的线程,就被对象B抢先占用了锁。

非公平锁在调用lock后,首先就会调用CAS进行一次枪锁,如果这个时候恰巧锁没有被占用,那么直接就获取到锁返回。而在CAS失败后,和公平锁一样都会进入tryAcquire()方法,在该方法中,如果锁释放了(state=0),非公平锁就会直接CAS枪锁,但是公平锁会判断等待队列是否有线程处在等待状态,没有则不去枪锁。相对来说非公平锁性能更好些,因为它的吞吐量比较大,当然非公平锁让获取锁的时间变得不确定,可能会导致在阻塞队列中的线程长期获取不到锁。

3、与synchronized比较总结
  • synchronized是独占锁,加锁和解锁的过程自动进行,方便操作,但不够灵活。
  • ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但是灵活。
  • synchronized是可重入锁,因为加锁和解锁自动进行,不必担心最后是否释放锁。
  • ReentrantLock也是可重入锁,但加锁和解锁需要手动进行,且加锁次数和解锁次数需一样,否则其他线程无法获取锁。
  • synchronized不可中断,一个线程获取不到锁就会一直等着。
  • ReentrantLock获取锁时,可以设置超时时间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值