前言

最近在看java并发编程这本书,已经看了点ReentrantLock的源码,以及之前有面试官问,公平锁和非公平锁有啥区别,我就只是从源码层面说了一下区别,但在性能上也有区别,今天就来说道说道。

公平与非公平

ReentrantLock的构造函数中提供了两种选择,默认创建非公平锁,也可以指定创建公平锁。
在公平锁上,线程将按照他们发出的请求顺序来获取锁,如果有另外一个线程持有这个锁或者有其他线程在队列中等待这个锁,那么新发出请求的线程就会被放到队列中。
在非公平锁上,允许“插队”:当一个线程请求非公平的锁时,如果在发出请求的同时该锁的状态变为可用,这个线程就会跳过队列中所有等待线程直接抢到这个锁。只有当锁被某个线程持有的时候,新发出请求的线程才会被放入队列中。

如何选择公平或非公平锁

为什么会有公平和非公平之分呢?我们都普遍认为一个公平的世界是一个稳定而温馨的世界,而不公平被认为不是好事,那么在锁的世界中如何呢?
当执行加锁操作时,公平性将由于挂起线程和恢复线程时存在的开销而大大降低性能。在实际的大多数情况中,非公平锁的性能要远高于公平锁的性能。

下图是Map的性能测试,并比较有公平的以及非公平的ReentrantLock包装的HashMap的性能,从图中可以看出,公平性把性能降低了约2个数量级:

备注ConcurrentHashMap在线程数为4到8之间有一些波动,这个波动属于测量噪声,这种噪声在性能测试中常有,对整体结果不造成实质性影响可不做过度关注。

从上图可以看出来,在激烈竞争下,非公平锁的性能远高于公平锁的性能,其原因是:在恢复一个被挂起的线程 与线程真正开始运行之间存在着严重的延迟。

  • 假设线程A持有一个锁,并且线程B请求这个锁。
  • 由于这个锁已经被线程A持有了,线程B将被放入队列中挂起。
  • 当A释放锁时,B将被唤醒,因此会再次尝试获取锁。
  • 与此同时,正好有个C线程来请求这个锁,那么C线程很有可能在B被完全唤醒之前抢到,使用以及释放这个锁。
  • 等C线程使用完释放后,B线程正好被唤醒,获取此锁并使用。

如此赢得了双赢的局面,线程B获取锁的时间并没有被延迟,C也在B唤醒的空挡中干完了自己的工作,因此最终的吞吐量也得以提高。

那么什么时候使用公平锁呢?
当持有的锁的时间相对较长,或者请求锁的平均时间间隔较长,那么应该使用公平锁。在这种情况下,“插队”带来的吞吐量的提升(当锁处于可用状态时,线程却还处于被唤醒的过程中)则可能不会出现。

ReentrantLock与内置锁

说到锁就不得不提我们最熟悉的内置锁:Sychronized,那么这两种锁又该如何选择呢?
ReentrantLock相比内置锁还通了包括定时的锁等待,可中断的锁等待,公平性,以及实现非块结构的枷锁。其性能上似乎是优于内置锁,其中在Java6略有胜出,在Java5则远远胜出。既然如此,我们为什么不抛弃内置锁,直接选择ReentrantLock呢?
原因在于

  • ReentrantLock的危险性比内置锁要高,如果忘记在finaly块中调用unlock方法,却虽然代码表面上可以正常运行,但却等于埋了一颗定时炸弹,还有可能伤及无辜。
  • 另外,Sychronized还有一个ReentrantLock所没有的优点,就是在线程转储中能给出在哪些调用帧中获得了那些锁,并能够检测和识别发生死锁的线程。在Java6中还提供了给管理和调试接口,锁可以通过该接口进行注册,从而一些相关的加锁信息就能出现在线程转储中,给程序员带来一些帮助。而ReentrantLock的非块状结构特性获取锁的操作不能与特定的栈帧关联起来,而内置锁却可以。
  • 未来更可能会提升Sychronized而不是ReentrantLock的性能。因为Sychronized是JVM内置属性,它能执行一些优化,例如对线程封闭的锁对象的锁消除优化,Java6开始的锁升级的优化。

那么什么时候该选择ReentrantLock呢?
在一些内置锁无法满足需求的情况下,ReentrantLock可以作为一种高级工具。当需要一些高级功能的时候才应该使用ReentrantLock,比如可定时的,可轮询的与可中断的锁获取操作,公平队列,以及非块状结构的锁。否则还是应该优先使用内置锁Sychronized

---------------你知道的越多,不知道的越多--------------

浅谈ReentrantLock的公平锁和非公平锁的区别相关推荐

  1. ReentrantLock与公平锁、非公平锁实现

    前言  最近开始读JDK源码,所有心得准备总结成一个专栏,JDK Analysis系列的第一篇,就从万众瞩目的ReentrantLock开始吧,而谈到ReentrantLock,就不得不说AQS,它是 ...

  2. 闲聊AQS面试和源码解读---可重入锁、LockSupport、CAS;从ReentrantLock源码来看公平锁与非公平锁、AQS到底是怎么用CLH队列来排队的?

    AQS原理可谓是JUC面试中的重灾区之一,今天我们就来一起看看AQS到底是什么? 这里我先整理了一些JUC面试最常问的问题? 1.Synchronized 相关问题以及可重入锁 ReentrantLo ...

  3. 深入分析ReentrantLock公平锁和非公平锁的区别 (转)

    在ReentrantLock中包含了公平锁和非公平锁两种锁,通过查看源码可以看到这两种锁都是继承自Sync,而Sync又继承自AbstractQueuedSynchronizer,而AbstractQ ...

  4. Java进阶:ReentrantLock实现原理解析(公平锁、非公平锁、可重入锁、自旋锁)

    概述 本篇将介绍公平锁.非公平锁.可重入锁.自旋锁相关理论知识,同时结合相关源码和Demo进行解析,主要是以ReentrantLock作为例子. 公平锁 公平锁定义 公平锁是指线程按照申请所的顺序来获 ...

  5. reentrantlock非公平锁不会随机挂起线程?_【原创】Java并发编程系列16 | 公平锁与非公平锁...

    本文为何适原创并发编程系列第 16 篇,文末有本系列文章汇总. 上一篇提到重入锁 ReentrantLock 支持两种锁,公平锁与非公平锁.那么这篇文章就来介绍一下公平锁与非公平锁. 为什么需要公平锁 ...

  6. 公平锁非公平锁的实际使用_理解ReentrantLock的公平锁和非公平锁

    学习AQS的时候,了解到AQS依赖于内部的FIFO同步队列来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成一个Node对象并将其加入到同步队列,同时会阻塞当 ...

  7. ReentrantLock 公平锁和非公平锁加锁和解锁源码分析(简述)

    - title: ReentrantLock 公平锁和非公平锁加锁和解锁源码分析(简述) - date: 2021/8/16 文章目录 一.ReentrantLock 1. 构造函数 二.Reentr ...

  8. java中ReentrantLock实现,公平锁和非公平锁,AQS并发队列,

    一般在java中,遇到并发的时候,我们很多时候可能会使用synchronized关键字来实现锁,但是synchronized关键字有一定的缺陷(比如无法实现类似读锁.非公平),而Lock可以实现.在j ...

  9. 6※、线程同步、同步锁、同步代码块的使用、同步锁释放的时机、ReentrantLock可重入锁、公平锁与非公平锁的区别、什么是死锁、线程间的通信(生产者和消费者模式)

    线程锁 1.※线程的同步:(要确保对象锁是一致的) 1.未使用同步锁的抢票 2.使用了同步锁的抢票 3.线程-同步代码块的使用 4.同步方法和代码块的区别 5.同步锁释放的时机 练习:多线程生产手机 ...

最新文章

  1. MIT与FAIR提出「mixup」,利用数据和标签的随机线性插值提高神经网络的健壮性
  2. win10任务管理器快捷键_你都知道吗?Win10任务管理器到底藏了多少秘密
  3. ubuntu20.04中gedit使用markdown插件(没搞定)
  4. lucene_indexWriter说明、索引库优化
  5. 使用.Net 1.1的项目,TreeView控件不能正常显示
  6. 基于 Sentry Hive 权限控制命令详解
  7. 机器学习笔记十二之异常检测
  8. 三维卷积神经网络预测MNIST数字详解
  9. 深入JS正则先行断言
  10. 罗永浩宣布年后回归科技界!下一代平台上见 网友:暗示年后“真还传”要完结...
  11. Lucene Boost 精度表
  12. Mac OS修改Mac地址
  13. 基于PaddleX实现电梯电瓶车检测
  14. 自动发射子弹c语言,C语言实现简单飞机大战
  15. vue日历加法定假假日
  16. 第二十八课:focusin与focusout,submit,oninput事件的修复
  17. 2019微信公开课 同行With Us 听课笔记及演讲全文
  18. 2022年全球市场机械蒸汽再压缩(MVR)总体规模、主要生产商、主要地区、产品和应用细分研究报告
  19. Error resolving template [], template might not exist or might not be accessible by any of the conf
  20. 小技巧使Windows Live Writer网络图片本地化

热门文章

  1. markdown编辑希腊字母
  2. 【C语言】删除指定字符
  3. 推荐一款可批量查询处理图片的「资源整理工厂」插件
  4. Python第十四次课堂作业(类和对象):商品类增加购买功能
  5. Python依赖库、安装包(源码安装)
  6. layui table th添加按钮,监听点击事件。
  7. vivado仿真 文件读取和写入
  8. 二次元属性被稀释,B站多了魔幻现实?
  9. 2019阿里云峰会-北京
  10. 熟练使用excel,并且知道excel能够实现什么