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

可重入锁 不可重入锁

在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/346646.shtml

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

相关文章

pythonista3安卓_Pythonista 3 app下载

Pythonista 3介绍 Pythonista is a complete scripting environment for Python, running directly on your iPadiPhone. It includes support for both Python 3.62.7, so you can use all the language improvements in Python 3, while still having 2.7 avAIlable for back…

linux查看本机所有预设的系统变量,如何设置与查看Linux系统中的环境变量?

大家都知道&#xff0c;在 Linux 系统中&#xff0c;有环境变量和 Shell 变量这两种变量。环境变量是在程序及其子程序中全局可用的&#xff0c;常常用来储存像默认的文本编辑器或者浏览器&#xff0c;以及可执行文件的路径等等这样的信息。而 Shell 变量仅在当前 Shell 中可用…

使用Amazon s3托管您的Maven工件

如果您使用Amazon Web Services并将Java用于项目&#xff0c;则Amazon S3是托管团队工件的理想场所。 它很容易设置&#xff0c;而且很便宜。 如果您对它们的功能不特别感兴趣&#xff0c;那么它比设置现有存储库选项&#xff08;jfrog&#xff0c;nexus&#xff0c;archiva等…

linux kill进程后黑屏,Linux中Kill进程的N种方法

常规篇&#xff1a;首先&#xff0c;用ps查看进程&#xff0c;方法如下&#xff1a;$ ps -ef……smx 1822 1 0 11:38 ? 00:00:49 gnome-terminalsmx 1823 1822 0 11:38 ? 00:00:00 gnome-pty-helpersmx 1824 1822 0 11:38 pts/0 …

ffmpeg宏块(Macroblock)概念

参考文章&#xff1a;音视频高手课系列5-h264编码基础(宏块原理) 文章目录 使用videoEye分析视频宏块示例FFmpeg宏块概念1. 宏块的定义2. 宏块的分类I-MacroblocksP-MacroblocksB-Macroblocks 3. 宏块的编码过程1. 运动估计2. 变换与量化3. 熵编码 4. 宏块的解码过程1. 熵解码2…

python123循环结构_来学Python啦,大话循环结构~

点击上方蓝字关注"程序员Bob"每日一句&#xff0c;送给最珍贵的你&#xff1a; 为学日益&#xff0c;为道日损&#xff0c;损之又损&#xff0c;以至于无为&#xff0c;无为而无不为。最近想研究爬虫了&#xff0c;准备拾起以前Python&#xff0c;继续学&#xff01;…

linux查看主机脚本,简单的bash脚本查看任意网段的在线主机

一前言最近看到许多同志在写ping某个地址段的bash脚本&#xff0c;我也心血来潮来了一发。 当然本人新手&#xff0c;大神勿喷。二准备工作linux系统的机器一台&#xff0c;当然虚拟机也可以&#xff0c;只要将网卡配置为桥接模式&#xff0c;可以连通其他局域网的主机即可。1…

python求一组数的最大值_python快速求一个数组的最大值/最小值及其索引

enumerate()函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列&#xff0c;同时列出数据和数据下标。 x [3, 2.2, 7.4, 6, 4] list(enumerate(x)) # 输出 [(0, 3), (1, 2.2), (2, 7.4), (3, 6), (4, 4)] operator.itemgetter()函数用于获取对象的哪些维…

linux远程调用的脚本在ssh时报错,linux:ssh远程调用tomcat脚本时候出错

执行 &dollar;Gulp 时发生了什么 —— 基于 Gulp 的前端集成解决方案(二)前言 文章 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一) 中,已经完成对 gulp 的安装,由于是window环境,文中特意提到了可以通过安装 gitbash 来代替 ...定制Eclipse IDE之插件篇(二)上…

python中什么叫合法的标识_python合法标识符要求是什么

python合法标识符要求是&#xff1a;1、不能以数字开头&#xff1b;2、不能包含非法字符&#xff1b;3、数字不能作为标识符&#xff1b;4、不能包含空格&#xff1b;5、不能包含运算符。1.不能以数字开头>>> 2bin2 File "", line 1 2bin2 ^ SyntaxError: i…

hibernate状态_Hibernate状态的自然身份证

hibernate状态自然ID是可以唯一标识实体的一个或一组属性。 我们最多可以为一个实体定义一个自然ID。 当Hibernate在实体映射文件中看到natural-id标记时&#xff0c;它会自动在构成natural-id的属性上创建唯一且非空的约束。 首先&#xff0c;让我们看一下简单和复合自然ID的示…

android界面实现框架内页面跳转_KVM虚拟化管理平台的实现

KVM虚拟化管理平台的实现源码链接&#xff1a;https://github.com/wsjhk/IaaS_admin.git视频演示链接&#xff1a;https://v.youku.com/v_show/id_XMjg4MTczODU1Ng.html(N年前刚开始学习Python时做的第一个自主设计实现项目&#xff0c;代码实在写的烂&#xff0c;不喜勿喷&…

suse linux 查看内存,Suse linux查询内存大小的指令是什么?

满意答案CJTHI2013.08.18采纳率&#xff1a;49% 等级&#xff1a;12已帮助&#xff1a;5850人下面和大家分享在Linux系统下查看内存使用情况的free命令&#xff1a;[rootscs-2 tmp]# freetotal used free shared buffers cachedMem: 3266180 3250004 16176 0 110652 2668236…

Java 8中的并行和异步编程

并行代码是在多个线程上运行的代码&#xff0c;曾经是许多经验丰富的开发人员的噩梦&#xff0c;但是Java 8带来了许多更改&#xff0c;这些更改应该使这种提高性能的技巧更加易于管理。 并行流 在Java 8之前&#xff0c;并行&#xff08;或并发&#xff09;代码与顺序代码之间…

Linux微信运行错误,Ubuntu 16.04 运行微信开发者工具编译出错的解决办法

最近有折腾小程序的意向&#xff0c;但微信的开发者工具只提供了 Windows 和 Mac 两个版本&#xff0c;对于我这样的 Linux 用户来说不是那么地友好。经过观察发现&#xff0c;那个开发者工具实际上是基于nw.js开发的&#xff0c;天然地具有跨平台的属性&#xff0c;搜索Github…

springboot security 权限校验_springboot借助aop和注解实现权限校验

我们用springboot做后台开发&#xff0c;难免会用到权限校验&#xff0c;比如查看当前用户是否合法&#xff0c;是否是管理员。而spring的面向切面的特效可以帮助我们很好的实现动态的权限校验。这里我们就用到的spring的aop。接下来就带领大家用aop和注解来快速的实现权限校验…

linux 应用网络连接失败的原因,PuTTY网络错误:软件导致连接中止

解决PuTTY网络错误Software caused connection abort阅读有关该错误的PuTTY怎么说这是Windows网络代码由于某种原因而终止已建立的连接时所产生的一般错误。例如&#xff0c;如果将网络电缆从连接以太网的计算机背面拔出&#xff0c;或者Windows出于其他类似原因认为整个网络都…

javaone_替代JavaOne 2013

javaone我对无法参加JavaOne 2013感到很失望&#xff0c;但是很高兴看到涵盖这个年度会议的大量有用帖子。 在这篇文章中&#xff0c;我链接到许多此类资源&#xff0c;并提供了每篇文章相对于JavaOne 2013讨论内容的简短摘要。 主题演讲 主题演讲是“大公告”趋向于发生的地方…

electron sqlite3_electron集成sqlite3,win10上折腾了2天

要看解决办法的&#xff0c;直接把文章滚动到最后就行了&#xff0c;很简单。最近要做个 IM&#xff0c;PC 端选择用 electron&#xff0c;跨端的最佳选择了。桌面端项目&#xff0c;肯定少不了本地数据库&#xff0c;本来想用 sql.js&#xff0c;看了下需要手动拼接 SQL 语句&…

linux下客户端与ntp同步时间,如何在Windows客户端和Linux NTP服务器之间同步时间?...

我希望我的Windows 7机器能够从我的Linux Debian Sid服务器中获取时间.所以我想提前并从Debian存储库安装OpenNTPD.默认情况下它不会监听任何内容,因此我将其配置如下&#xff1a;listen on 192.168.0.1server 0.debian.pool.ntp.orgserver 1.debian.pool.ntp.orgserver 2.debi…