一个小例子帮助理解(我们常用的synchronized也是可重入锁)

话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝。由于井水有限,大家只能依次打水。为了实现家家有水喝,户户有水用的目标,村长绞尽脑汁,最终想出了一个比较合理的方案。

首先,在水井边上安排一个看井人,负责维持秩序。

然后,打水时,以家庭为单位,哪个家庭任何人先到井边,就可以先打水,而且如果一个家庭占到了打水权,其家人这时候过来打水不用排队。而那些没有抢占到打水权的人,一个一个挨着在井边排成一队,先到的排在前面。

最后,打水的人打完水以后就告诉看井人,看井人就让等待的队伍中的最前面一个去打水。

这样一来,大家都能打到水,也保证了相对的公平。这就是公平锁的基本思路。

随着时间的推移,村民发现每次去打水的时候都需要排队,想着每次排队都浪费时间,于是就把水桶放在井边代替,自己则溜回家去了。这样一搞,可把看井人累坏,经常往村民家里跑,让他们来打水。于是聪明的看井人想出了一个对策,如果有人打完水后,刚好又有其它人来打水,就直接让这个新来的人上去打水,不用到队伍末尾去排队等候。

这种方式虽然看上去不公平,但是他节省了资源,提高了打水的性能,这就是非公平锁的基本思路。

打水的小故事在java中的应用

Java中可重入锁-ReentrantLock基本上就是按照上面的思路来实现的,我们来对给他们做一个简单的对比。

一次只有一个人能打水 锁需要保证多线程的同步。

必须严格按照排队顺序打水 ReentrantLock提供的公平锁功能。

来得早不如来得巧 ReentrantLock提供的非公平锁功能。

有家人正在打水的时候就不需要排队 ReentrantLock的可重入特性。

那么可重入锁又是怎样实现上面那些特性的呢?

java可重入锁-ReentrantLock实现细节

首先我们从上面的故事入手,看看ReentrantLock中的各个角色都是怎么样的。

打水权 volatile int state

打水者 线程、Thread

打水队伍 双向链表Node

获取锁的时候,公平锁的整个工作流程就如下图所示:

可重入公平锁获取流程

在获取锁的时候,如果当前线程之前已经获取到了锁,就会把state加1,在释放锁的时候会先减1,这样就保证了同一个锁可以被同一个线程获取多次,而不会出现死锁的情况。这就是ReentrantLock的可重入性。

对于非公平锁而言,调用lock方法后,会先尝试抢占锁,在各种判断的时候会先忽略等待队列,如果锁可用,就会直接抢占使用。

释放锁的时候,整个工作流程如下图:

可重入锁释放过程

本文为转载:https://baijiahao.baidu.com/s?id=1594800969528243663&wfr=spider&for=pc
参考:https://blog.csdn.net/yanyan19880509/article/details/52345422

java 可重入锁ReentrantLock的介绍的更多相关文章

  1. 轻松学习java可重入锁(ReentrantLock)的实现原理

    转载自https://blog.csdn.net/yanyan19880509/article/details/52345422,(做了一些补充) 前言 相信学过java的人都知道 synchroni ...

  2. 轻松学习java可重入锁(ReentrantLock)的实现原理(转 图解)

    前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...

  3. java可重入锁reentrantlock

    public class ReentrantDemo { //重入锁 保护临界区资源count,确保多线程对count操作的安全性 /*public static ReentrantLock rtlo ...

  4. Java 重入锁 ReentrantLock 原理分析

    1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...

  5. Java 显示锁 之 重入锁 ReentrantLock(七)

    ReentrantLock 重入锁简介 重入锁 ReentrantLock,顾名思义,就是支持同一个线程对资源的重复加锁.另外,该锁还支持获取锁时的公平与非公平性的选择. 重入锁 ReentrantL ...

  6. synchronized关键字,Lock接口以及可重入锁ReentrantLock

    多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...

  7. 17_重入锁ReentrantLock

    [概述] 重入锁可以完全代替synchronized关键字. 与synchronized相比,重入锁ReentrantLock有着显示的操作过程,即开发人员必须手动指定何时加锁,何时释放锁,所以重入锁 ...

  8. Java不可重入锁和可重入锁的简单理解

    基础知识 Java多线程的wait()方法和notify()方法 这两个方法是成对出现和使用的,要执行这两个方法,有一个前提就是,当前线程必须获其对象的monitor(俗称“锁”),否则会抛出Ille ...

  9. Java中可重入锁ReentrantLock原理剖析

    本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQue ...

随机推荐

  1. webGL之three.js入门2

    入门建议: webGL中文翻译教程,基于NeHe的openGL教程:http://www.hiwebgl.com/?p=42 . WebGL中文网 http://www.hewebgl.com/ ,里 ...

  2. Observable讲解

    参见这里 总结: Observable是传统观察者+链式模式的函数式实现 Observable官方文档 还是比较喜欢EventBus,简单粗暴,angular-event-service可支持angu ...

  3. Wsus 清理的计划任务

    <# Get-ExecutionPolicy 默认为 RemoteSigned 该签名设置 Set-ExecutionPolicy Unrestricted 添加到排除 powershell - ...

  4. Flask--异常处理

    异常处理: abort(404)-捕获HTTP抛出的统一状态码 @app.errorhandler-捕获全局异常错误码,捕获异常错误 @app.route("/demo4") de ...

  5. JS一行代码,生成一个16进制随机颜色,简单粗暴。

    var color = '#'+ Math.random().toString(16).substr(-6); document.body.style.backgroundColor = color; ...

  6. 数据仓库专题19-数据建模语言Information Engineering - IE模型(转载)

    Information Engineering采用Crow's Foot表示法(也有叫做James Martin表示法的),中文翻译中对使用了Crow's Foot表示法的模型也有笼统的称做鸭掌模型的 ...

  7. Qt应用程序单实例化

    在实际应用中,我们经常需要让应用程序只有一个实例,再打开新的文档或者页面时,只是替换现在的窗口或者新打开一个标签,而不是重新启动一次应用程序.Qt中是否可以做到这样呢,答案是肯定的,因为Qt本身可以直 ...

  8. Java学习——Applet画8个同心圆

    import java.awt.*; import java.applet.*; public class GUI3 extends Applet{ public void paint(Graphic ...

  9. Scrapy学习篇(一)之框架

    概览 在具体的学习scrapy之前,我们先对scrapy的架构做一个简单的了解,之后所有的内容都是基于此架构实现的,在初学阶段只需要简单的了解即可,之后的学习中,你会对此架构有更深的理解.下面是scr ...

  10. ueditor 正在读取目录

    ueditor 版本为1.3.6  项目版本为2.0 引用 <script src="../ueditor/ueditor.config.js" type="tex ...