什么是可重入锁?

在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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366617.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多选一的图片和文字

利用 radio 做单选事件&#xff0c;js 兄弟选择 nextSibling 获取邻近的图片对象&#xff0c;然后进行改变 例子&#xff1a; CSS <style type"text/css">input[type"radio"] {display: none;}label{font-size: 16px;}.choose_or{width: 1.2rem;heig…

【每日一题】收集足够苹果的最小花园周长

文章目录 Tag题目来源解题思路方法一&#xff1a;二分枚举答案 写在最后 Tag 【二分枚举答案】【二维网格】【2023-12-24】 题目来源 1954. 收集足够苹果的最小花园周长 解题思路 方法一&#xff1a;二分枚举答案 思路 通过如下过程&#xff0c;我们可以求出边长为 2n 时&…

小数前的0在html不显示,jsp小数显示问题 例如 我在oracle 数据库中查询出来的是 0.01 但是在jsp页面上就显示成 .01 没有前面的0...

满意答案1234junling2013.08.28采纳率&#xff1a;56% 等级&#xff1a;12已帮助&#xff1a;6022人控制保留几位有效小数的js函数//Code CreateBy abandonship 2007.03.12function FormatAfterDotNumber( ValueString, nAfterDotNum ){var ValueString,nAfterDotNum ;var r…

word文档图标变成白纸_word文档图标变为白纸

请不要盗用我的答案&#xff01;&#xff01;一号方案【新P】注意【原创】&#xff1a;1&#xff0e;安全模式下&#xff0c;效果更好&#xff01;2. 以下所要使用的软件&#xff0c;都要安装或升级到最新版本&#xff0c;以保证使用的效果。3. 不杀毒&#xff0c;直接使用以下…

Jira filter subscribe issues

Jira & filter & subscribe & issues https://confluence.atlassian.com/search/?querysubscribeissues&productNameJiraCore&productVersion7.3]https://confluence.atlassian.com/jiracoreserver073/saving-your-search-as-a-filter-861257224.html 转载…

iView 一周年了,同时发布了 2.0 正式版,但这只是开始...

两年前&#xff0c;我开始接触 Vue.js 框架&#xff0c;当时就被它的轻量、组件化和友好的 API 所吸引。之后我将 Vue.js 和 Webpack 技术栈引入我的公司&#xff08;TalkingData&#xff09;可视化团队&#xff0c;并经过一年多的实践&#xff0c;现已成为整个公司的前端开发规…

Hawtio和Apache JClouds

介绍 我最近花了一些时间为Hawtio开发 Apache Jclouds插件。 尽管还有很多待完成的工作&#xff0c;但我无法激动&#xff0c;想分享…… 这个Hawtio到底是什么&#xff1f; 每当我注意到一个很酷的开源项目时&#xff0c;我通常都会订阅邮件列表&#xff0c;以便我可以更好地…

【转】安全加密(一):这些MCU加密方法你都知道吗?

本文导读 随着物联网和边缘计算的出现&#xff0c;五花八门的MCU也被应用其中&#xff0c;如何保证我们的程序安全和知识产权不受侵犯呢&#xff0c;本文我们将对主流MCU的程序加密进行讲解&#xff0c;希望能够帮助你选择最适合自己应用的微处理器。 1. MCU加密 通常所说的MC…

检验杜宾 瓦森检验法R语言_EVIEWS序列相关检验2.pdf

EVIEWS序列相关检验2序列相关检验、处理及案例内蒙古科技大学经济与管理学院边璐 2011.11.10内容安排• 自相关性的检验• 自相关性的解决方法• 案例分析自相关性的检验• 1、图示法(上节课已说过)• 2、DW检验• 3、回归检验法• 4、高阶自相关性检验2、杜宾-瓦森(Durbin-Wat…

连续出现最长次数

输入第一行有一个整数n(n < 1000)&#xff0c;为数组元素的个数。第二行有n个整数&#xff0c;整数之间以一个空格分开。输出输出最长平台的长度。样例输入 10 1 2 2 3 3 3 4 5 5 6 样例输出 3 #include<iostream> using namespace std; int main() {int a[1001],n;ci…

家用计算机机箱怎么选,一般家用电脑主机买什么配置的比较好

组装台式电脑配置最好的方法&#xff1a;实用性机型建议&#xff1a;首选1&#xff1a;intel G1620双核H61M主板。(价格低廉性能不弱&#xff0c;超值)首选2&#xff1a;intel G1840双核H81M主板。(核心显卡性能比G1620更强)中级机型建议&#xff1a;首选1&#xff1a;intel G3…

浅谈Vue内置component组件的应用场景

官方的说明 渲染一个“元组件”为动态组件。依 is 的值&#xff0c;来决定哪个组件被渲染。 <!-- 动态组件由 vm 实例的属性值 componentId 控制 --> <component :is"componentId"></component>具体可以官网文档中的 动态组件内置的组件compone…

angular路由传递参数_在angular4.0路由传递获取参数的最优方案

这次给大家带来在angular4.0路由传递获取参数的最优方案&#xff0c;在angular4.0路由传递获取参数的注意事项有哪些&#xff0c;下面就是实战案例&#xff0c;一起来看一下。研究ng4的官网&#xff0c;终于找到了我想要的方法。我想要的结果是用‘&拼接参数传送&#xff0…

计算机基础及ms应用在线,全国一级计算机基础及MS Office应用课件 (2).pdf

全国计算机等级考试一级教程计算机基础及MS Office应用考试大纲考试大纲考试大纲考试大纲考试大纲考试大纲考试大纲考试大纲考点1 &#xff1a;计算机组成结构1946年世界上第一台名为ENIAC的电子计算机诞生于美国宾夕法尼亚大学。考点2 &#xff1a;冯诺依曼概念 冯诺依曼理论…

破坏您的JVM

正如我们最近发现的那样&#xff0c;全面测试可能有害。 扩展测试覆盖范围导致我们仅花费一行代码就进行了几个小时的调试会话。 使调试特别令人不愉快的是&#xff0c;该代码不仅崩溃了所部署的JVM&#xff0c;而且还破坏了其下的虚拟机和/或物理机。 因此&#xff0c;请自行…

ulli*3 实现翻书动画效果

按惯例&#xff0c;上GIF&#xff1a;重现&#xff1a;https://codepen.io/anon/pen/JJBxOm 这是我今天参加面试时候&#xff0c;面试官让我做的一道题&#xff0c;面试官坐我旁边看我现场做&#xff0c;然而我比较菜&#xff0c;回来后才做出来…… 来看看HTML部分&#xff1a…

软件结构B/S和C/S

C/S(Client Server)结构的软件&#xff1a; 比如&#xff1a; QQ、 极品飞车、 飞信 、 迅雷 缺点&#xff1a;更新的时候需要用户下载更新包然后再安装&#xff0c;程序员则需要开发客户端与服务端。优点&#xff1a; 减轻服务端的压力&#xff0c;而且可以大量保存数据…

对hash签名失败_vue项目中微信jssdk在ios签名失败

一、问题描述1. vue项目中微信jssdk签名时&#xff0c;在安卓和ios是有差异的&#xff0c;签名时使用的urlwindow.location.href.split(#)[0],此时在安卓没问题&#xff0c;在ios会导致签名失败。因为在安卓中应该拿去签名的URL就是每个页面的URL&#xff0c;在ios中拿去签名的…

cookie,session 会话跟踪技术

会话跟踪技术 1 什么是会话跟踪技术 我们需要先了解一下什么是会话&#xff01;可以把会话理解为客户端与服务器之间的一次会晤&#xff0c;在一次会晤中可能会包含多次请求和响应。例如你给10086打个电话&#xff0c;你就是客户端&#xff0c;而10086服务人员就是服务器了。…

嵌入Maven

这是一个非常罕见的用例&#xff0c;但有时您需要它。 如何在应用程序中嵌入Maven&#xff0c;以便可以以编程方式运行目标&#xff1f; 简短的答案是&#xff1a;这很棘手。 我涉足了我的java webapp自动同步项目的问题 &#xff0c;有时我决定不嵌入它。 最终&#xff0c;我…