ReentrantLock 重入锁(互斥锁)

参考博客:https://blog.csdn.net/jiangjiajian2008/article/details/52226189

Synchronized是依赖于JVM实现的,而ReenTrantLock是JDK实现的

与synchronized相比,重入锁有着显式的操作过程,开发人员必须手动的指定何时加锁(调用lock方法),何时释放锁(调用unlock方法)。因此,重入锁对逻辑的控制性要好于synchronized。

重入锁,顾名思义,对于同一个线程,这种锁是可以反复进入的。如果一个线程多次获得锁,那么在释放锁的时候,也必须释放相同的次数。

ReenTrantLock的一些主要方法

ReenTrantLock(boolean fair)

ReenTrantLock有两个构造方法,一个空参,另一个ReenTrantLock(boolean fair)当参数fair=true时,表示构造一个公平锁。synchronized是非公平锁,公平锁会按时间顺序,先唤醒等待队列中等待的线程。公平锁的一大特点就是不会产生饥饿现象。但是,由于实现公平锁要求系统维护一个有序队列,因此实现公平锁的成本很高,性能也相对低下。因此,默认情况锁是非公平的。

lock()

获得锁,如果锁已经被占用,则等待

lockInterruptibly()

获得锁,但优先响应中断。如果当前线程未被中断,则获取锁

tryLock()

尝试获得锁,如果成功放回true,失败返回false,该方法不等待,立即返回

unlock()

释放锁

newCondition()

返回与lock实例一起使用的Condition对象

使用ReentrantLock类的newCondition()方法可以获取Condition对象

* 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法

* 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了,而synchronized是随机唤醒线程的

Condition接口:此接口中封装了awiat(),signal(),signalAll(),方法。代替了原来锁中的wait(),notify(),notifyAll()监视器方法

ReenTrantLock的特点:

1.ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。

2.ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。

3.ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。

应用场景:需要使用以上三个特点时,使用ReenTrantLock。

ReenTranLock解决死锁的方式:

  1. 响应中断

通过lock.lockInterruptibly()方法来实现。对于synchronized来说,对于一个线程在等待锁。那么只有两种情况,要么获得锁,要么保持等待。重入锁提供另一种可能中断,如果一个线程在等待锁,如果它收到一个通知,被告知无需再等待,可以停止工作了。这种情况对于处理死锁是有帮助的

  1. 锁申请等待限时

通过lock.tryLock()方法来实现。如果其他线程占有锁,则当前线程不会等待,立即返回false。tryLock(long ,TimeUnit),tryLock方法既可以接受无参调用,还可以接受参数,第一个参数等待时长,第二个表示计时单位。如果超过等待时长还没有获取到锁,会停止等待并返回false。

 

tryLock和lock和lockInterruptibly三个方法的区别

(1)tryLock仅在其他线程未保持锁时,才获取锁,并立即返回true。

如果锁已经被其他线程保持,就立即返回false。tryLock(long timeout,TimeUnit unit),可以增加时间限制,如果超过该时间段还没获得锁,返回false。

(2)lock能获得锁就返回true,不能的话一直等待获得锁

(3)lock和lockInterruptibly,如果两个线程分别执行这两个方法,但此时中断这两个线程,前者不会抛出异常,而后者会抛出异常InterruptedException。lockInterruptibly方法在其他线程在中断当前线程时,在抛出异常的同时,会停止等待获取锁。

Condition的使用

* 使用ReentrantLock类的newCondition()方法可以获取Condition对象

* 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法

* 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了

Lock接口:Lock接口的出现代替了同步代码块和同步函数。将同步的隐式锁操作变成了显示锁操作,同时也变得更加灵活。一个锁可以加上多组监视器。

Lock接口中的一些方法:lock()//获取锁,unlock()//释放锁通常需要定义在finally代码块中。

Condition接口:此接口中封装了awiat(),signal(),signalAll(),方法。代替了原来锁中的wait(),notify(),notifyAll()监视器方法

ReentranLock的底层实现(源码解析)

参考博客:https://blog.csdn.net/jiangjiajian2008/article/details/52226189

在ReentranLock中有一个抽象静态内部类Sync,Sync继承了AbstractQueuedSynchronizer(以下简称AQS)。同时还有两个静态内部类NofairSync和FairSync,这两个类都继承了Sync。在创建ReentranLock对象时,如果要创建公平锁则会创建FairSync的实例,反之则创建NofairSync的实例。

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值