可重入锁

在Java 5.0中,增加了一个新功能以增强内部锁定功能,称为Reentrant Lock。 在此之前,“同步”和“易失”是实现并发的手段。

public synchronized void doAtomicTransfer(){//enter synchronized block , acquire lock over this object.operation1()operation2();
} // exiting synchronized block, release lock over this object.

同步使用内部锁或监视器。 Java中的每个对象都有一个与之关联的固有锁。 每当线程尝试访问同步的块或方法时,它都会获取该对象的固有锁定或监视器。 在使用静态方法的情况下,线程获取对类对象的锁定。

就编写代码而言,内在锁定机制是一种干净的方法,对于大多数用例而言,它是相当不错的。 那么,为什么我们需要显式锁的其他功能? 让我们讨论。

内部锁定机制可能具有一些功能限制,例如:

  1. 无法中断等待获取锁的线程。 (间断锁定)
  2. 如果不想永远等待,就不可能尝试获取锁。 (尝试锁定)
  3. 无法实现非块结构的锁定规则,因为必须在获取它们的同一块中释放固有锁。

除此之外,ReentrantLock还支持锁定轮询和支持超时的可中断锁定等待。 ReentrantLock还支持可配置的公平性策略,从而允许更灵活的线程调度。

让我们看一下ReentrantLock类(实现Lock)实现的几种方法:

void lock();void lockInterruptibly() throws InterruptedException;boolean tryLock();boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
.....

让我们尝试了解它们的用法,看看我们可以得到什么好处。

  1. 轮询和定时锁获取:

    让我们看一下示例代码:

    public void transferMoneyWithSync(Account fromAccount, Account toAccount,float amount) throws InsufficientAmountException {synchronized (fromAccount) {// acquired lock on fromAccount Objectsynchronized (toAccount) {// acquired lock on toAccount Objectif (amount > fromAccount.getCurrentAmount()) {throw new InsufficientAmountException("Insufficient Balance");} else {fromAccount.debit(amount);toAccount.credit(amount);}}}}

    在上面的transferMoney()方法中,当2个线程A和B几乎同时尝试转移资金时,可能会出现死锁。

    A: transferMoney(acc1, acc2, 20);
    B: transferMoney(acc2, acc1 ,25);

    线程A可能已获得对acc1对象的锁定,并正在等待获取对acc2对象的锁定,同时线程B已获得了对acc2对象的锁定,并且正在等待对acc1的锁定。 这将导致死锁,并且必须重新启动系统!

    但是,有一种避免这种情况的方法,也就是所谓的“锁定排序”,我个人认为这有点复杂。

    ReentrantLock使用tryLock()方法实现了一种更干净的方法。 这种方法称为“定时和轮询锁定获取”。 如果您无法获取所有必需的锁,释放已获取的锁并重试,它可以让您重新获得控制权。

    因此,使用tryLock我们将尝试获取两个锁,如果无法同时获取这两个锁,则如果已经获取了其中之一,则释放它,然后重试。

    public boolean transferMoneyWithTryLock(Account fromAccount,Account toAccount, float amount) throws InsufficientAmountException, InterruptedException {// we are defining a stopTimelong stopTime = System.nanoTime() + 5000;while (true) {if (fromAccount.lock.tryLock()) {try {if (toAccount.lock.tryLock()) {try {if (amount > fromAccount.getCurrentAmount()) {throw new InsufficientAmountException("Insufficient Balance");} else {fromAccount.debit(amount);toAccount.credit(amount);}} finally {toAccount.lock.unlock();}}} finally {fromAccount.lock.unlock();}}if(System.nanoTime() < stopTime)return false;Thread.sleep(100);}//while}

    在这里,我们实现了定时锁,因此,如果在指定时间内无法获取锁,则transferMoney方法将返回失败通知并正常退出。

    我们还可以使用此概念来维护时间预算活动。

  2. 可中断锁获取:

    可中断的锁获取允许在可取消的活动中使用锁。

    lockInterruptible方法使我们能够尝试获取锁,但可用于中断。 所以基本上这意味着它允许线程立即响应从另一个线程发送给它的中断信号。当我们想向所有等待的锁发送KILL信号时,这将很有帮助。

    让我们看一个例子,假设我们有一条共享的线来发送消息,我们希望以这样的方式进行设计:如果另一个线程来了并中断了当前线程,则该线程应释放锁并执行退出或关闭操作以取消当前任务。

    public boolean sendOnSharedLine(String message) throws InterruptedException{lock.lockInterruptibly();try{return cancellableSendOnSharedLine(message);} finally {lock.unlock();}}private boolean cancellableSendOnSharedLine(String message){
    .......

    定时tryLock也可响应中断。

  3. 非块结构锁定:

    在固有锁中,获取释放对是块结构的,即,无论控制如何退出该锁,始终在获取该锁的同一基本块中释放该锁。

    外部锁提供了进行更明确控制的功能。使用外部锁可以更轻松地实现一些概念,例如“锁紧皮带”。 在哈希混和集合和链接列表中可以看到一些用例。

  4. 公平:

    ReentrantLock构造函数提供两个公平选项的选择:创建非公平锁或公平锁。 使用公平锁线程只能按请求的顺序获取锁,而不公平锁则允许锁轮流获取锁,这称为交换(打破队列并在锁可用时获取锁)。

    由于挂起和恢复线程的开销,公平锁定会带来巨大的性能成本。 在某些情况下,恢复挂起的线程与实际运行之间会有明显的延迟。 让我们看一下情况:

    A -> holds lock
    B -> has requested and is in suspended state waiting for A to release lock
    C -> requests the lock at the same time when A releases the lock, C has not yet gone to suspended state.

    由于C尚未处于挂起状态,因此它有可能获得A释放的锁,使用它并在B甚至还没有完成唤醒之前释放它。 因此,在这种情况下,不公平锁定具有明显的性能优势。

    内部锁和外部锁在内部具有相同的锁定机制,因此性能的提高纯粹是主观的。 这取决于我们上面讨论的用例。 外部锁提供了更明确的控制机制,可以更好地处理死锁,饥饿等。我们将在以后的博客中看到更多示例。

参考:什么是可重入锁? 从我们的JCG合作伙伴Anirudh Bhatnagar在anirudh bhatnagar博客上获得。

翻译自: https://www.javacodegeeks.com/2013/11/what-are-reentrant-locks.html

可重入锁

可重入锁_什么是可重入锁?相关推荐

  1. 可重入锁 不可重入锁_什么是可重入锁?

    可重入锁 不可重入锁 在Java 5.0中,增加了一个新功能以增强内部锁定功能,称为可重入锁定. 在此之前,"同步"和"易失性"是实现并发的手段. public ...

  2. java 内置锁_深入理解java内置锁(synchronized)和显式锁(ReentrantLock)

    synchronized 和 Reentrantlock 多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两种同 ...

  3. python gil全局锁_什么是Python全局解释器锁(GIL)?

    python gil全局锁 The Python Global Interpreter Lock or GIL, in simple words, is a mutex (or a lock) tha ...

  4. mysql如何加悲观锁_【mysql】关于悲观锁

    关于mysql中的锁 在并发环境下,有可能会出现脏读(Dirty Read).不可重复读(Unrepeatable Read). 幻读(Phantom Read).更新丢失(Lost update)等 ...

  5. mysql mdl 锁_详细分析mysql MDL元数据锁

    前言: 当你在MySQL中执行一条SQL时,语句并没有在你预期的时间内执行完成,这时候我们通常会登陆到MySQL数据库上查看是不是出了什么问题,通常会使用的一个命令就是 show processlis ...

  6. mysql insert 乐观锁_【mysql】关于乐观锁

    一.乐观锁介绍 乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检,乐观锁适用于 ...

  7. 轻量级锁_并发编程实战05:锁的状态

    无锁.偏向锁 .轻量级锁和重量级锁这四种锁是指锁的状态,专门针对synchronized的.在介绍这四种锁状态之前还需要介绍一些额外的知识. 首先为什么Synchronized能实现线程同步?在回答这 ...

  8. java synchronized 类锁_【java】synchronized对象锁和类锁简介【图文教程】

    平凡也就两个字: 懒和惰; 成功也就两个字: 苦和勤; 优秀也就两个字: 你和我. 跟着我从0学习JAVA.spring全家桶和linux运维等知识,带你从懵懂少年走向人生巅峰,迎娶白富美! 关注微信 ...

  9. java 对象锁_个人对java中对象锁与类锁的一些理解与实例

    一  什么是对象锁 对象锁也叫方法锁,是针对一个对象实例的,它只在该对象的某个内存位置声明一个标识该对象是否拥有锁,所有它只会锁住当前的对象,而并不会对其他对象实例的锁产生任何影响,不同对象访问同一个 ...

最新文章

  1. 2020新版IDEA创建Web工程(包括添加Tomcat服务器、第三方jar包)
  2. SpringFramework的简介
  3. 浅谈ROS操作系统及其应用趋势
  4. express : 无法将“express”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。express: command not found
  5. python 类的细节
  6. SQL不能以实例名连接问题处理
  7. linux服务器 网速测试
  8. 240万!动漫人脸数据集AnimeCeleb
  9. 基于JavaScript的Web端股票价格查看器——大道
  10. while在c语言中的作用,while的用法_C语言中while的用法
  11. 非标自动化转行机器人_工作4年,自动化工程师该不该转行
  12. Proxmox VE 多机系统备份
  13. python3查找元素在数组位置_Python:查找数组中元素的位置
  14. less模块——math函数
  15. OSAL(操作系统抽象层)
  16. ​ 每周一书《数学之美 第二版》分享!
  17. python里使用asyncore模块
  18. python自动发邮件报554错误_python-自动化测试结果发送邮件报错(smtplib.SMTPDataError: (554, b'DT:SPM 163……)解决方法...
  19. python 三维矩阵乘以二维矩阵_二维numpy数组的乘法/除法生成三维数组
  20. 离散数学实验一 真值计算

热门文章

  1. 机器学习与R之朴素贝叶斯分类器
  2. GPS周和周内秒转公历时间 以及 公历时间转GPS周和周内秒 (python版)
  3. 看完Alibaba“Java成长笔记”我懂了! 为什么阿里的程序员成长如此之快?
  4. 【配送路径规划】蚁群算法求解配送路径最短问题【含Matlab源码 2222期】
  5. 嵌入式系统232串口测试笔记
  6. android二维码制作
  7. PARSEC使用与下载
  8. 预处理--python实现用随机森林评估特征的重要性
  9. Unity-3d Day03 做了一个吃粑粑豆的小游戏 hiahia~~
  10. microduino与onetnet测试