可重入锁 不可重入锁

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

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. 临键锁如何实现幻读_如何用Redis实现分布式锁?

    作者:敖丙 来源:https://juejin.im/post/5e9473f5e51d454702460323 前言 上一章节我提到了基于zk分布式锁的实现,这章节就来说一下基于Redis的分布式锁 ...

  2. 深入Lock锁底层原理实现,手写一个可重入锁

    synchronized与lock lock是一个接口,而synchronized是在JVM层面实现的.synchronized释放锁有两种方式: 获取锁的线程执行完同步代码,释放锁 . 线程执行发生 ...

  3. 第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁【Java面试题】

    第二季:5值传递和引用传递[Java面试题] 前言 推荐 值传递 说明 题目 24 TransferValue醒脑小练习 第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自 ...

  4. mysql可重复读和间隙锁_解决MySQL可重复读——详解间隙锁

    间隙锁(Gap Lock)是Innodb在可重复读提交下为了解决幻读问题时引入的锁机制,(下面的所有案例没有特意强调都使用可重复读隔离级别)幻读的问题存在是因为新增或者更新操作,这时如果进行范围查询的 ...

  5. 递归重入c语言延时函数多任务程序设计中的函数重入问题按照Keil的规范对函数添加关键字“reentrant”,将函数定义为可重入的 void Delay_MS(x) reentrant

    c语言延时函数_子牙篇(2)多任务程序设计中的函数重入问题 weixin_39559333 2020-11-29 09:07:44  39  收藏 文章标签: c语言延时函数 c语言延时函数delay ...

  6. java锁的有哪些_「并发编程」Java锁分类和特点有哪些

    公平锁.非公平锁:公平锁指多个线程按照申请锁的顺序来获取锁,非公平锁就是没有顺序完全随机,所以能会造成优先级反转或者饥饿现象:synchronized 就是非公平锁,ReentrantLock(使用 ...

  7. java并发框架支持锁包括,tip/面试题_并发与多线程.md at master · 171437912/tip · GitHub...

    01. java用()机制实现了进程之间的同步执行 A. 监视器 B. 虚拟机 C. 多个CPU D. 异步调用 正解: A 解析: 监视器机制即锁机制 02. 线程安全的map在JDK 1.5及其更 ...

  8. educoder 使用线程锁(lock)实现线程同步_性能:Lock的锁之优化

    Lock / synchronized Lock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁 synchronizedLock实现方式JVM层实现Java底层代码实 ...

  9. Redis 学习笔记-NoSQL数据库 常用五大数据类型 Redis配置文件介绍 Redis的发布和订阅 Redis_事务_锁机制_秒杀 Redis应用问题解决 分布式锁

    1.NoSQL数据库 1.1 NoSQL数据库概述 NoSQL(NosQL = Not Only sQL ),意即"不仅仅是sQL",泛指非关系型的数据库.NoSQL不依赖业务逻辑 ...

最新文章

  1. 专访北京飞搜科技:一个创业公司该怎样在人工智能大潮中成长
  2. YIFullScreenScroll
  3. BOOST_SCOPE_EXIT宏相关的测试程序
  4. Spring Batch中面向TaskletStep的处理
  5. c++的虚拟继承 的一些思考吧
  6. 通过boundingRectWithSize:options:attributes:context:计算文本尺寸
  7. python三大编程语言_程序员最需要的三种编程语言
  8. C语言:学生信息管理程序
  9. Web Hacking 101 中文版 十一、SQL 注入
  10. 账号类型_2019年头条、百家、大鱼、企鹅四平台哪种类型的账号最受欢迎?
  11. mysql5和8怎么同时安装_WINDOWS服务器同时安装多个版本的MYSQL的方法,MQYSQL5和MQYSQL8的共存。...
  12. java.lang.NoClassDefFoundError: org/springframework/core/metrics/ApplicationStartup
  13. Github下载 arduino库下载
  14. wex5 java_WeX5简介
  15. 算法笔记_110:第四届蓝桥杯软件类省赛真题(JAVA软件开发高职高专组部分习题)试题解答...
  16. Archlinuxarm / AUR的国内镜像源(for Banana Pi / Raspberry Pi , etc)(更新)
  17. MMGG测评 感动全球的链上自走棋——HeroesEmpires游戏拆解
  18. 什么是CISAW认证?有什么价值?
  19. c#windows编程视频教程
  20. 数据治理、共享交换、数据仓库、数据中心的关系

热门文章

  1. CF449B Jzzhu and Cities(Dijkstra)
  2. 一道有趣的最短路 NEERC2017 Journey from Petersburg to Moscow
  3. Problem H Rock Paper Scissors,FFT
  4. MySQL dayofweek()函数
  5. java程序员被误导的一个概念,Set也可以有序
  6. Java 9 中的9个新特性
  7. 【分享】通过手游赚¥
  8. FastDFS(分布式文件系统)
  9. android拦截短信获取短信内容,《英雄联盟手游》先锋测试招募说明:仅安卓用户...
  10. centos普通用户修改文件权限_用户管理(特殊权限、特殊属性、umask 默认权限 )