图解:为什么非公平锁的性能更高?

作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

在 Java 中 synchronized 和 ReentrantLock 默认使用的都是非公平锁,而它们采用非公平锁的原因都是一致的,都是为了提升程序的性能。那为什么非公平锁就能提升性能呢?接下来我们一起来看。

非公平锁

非公平锁:每个线程获取锁的顺序是随机的,并不会遵循先来先得的规则,任何线程在某时刻都有可能直接获取并拥有锁。这就好比磊哥去加油,到了加油站之后发现前面有人在加,于是我就在车里刷起了抖音,过了一会,前面的车加完油走了,但磊哥没注意到,还在车里愉快的刷着抖音。然而此时加油站又来了一辆车,发现有空闲的油枪,于是就抢先在磊哥之前把油加了。这里的油枪就是锁,没有按照到达的先后顺序得到油枪,这就是非公平锁。

公平锁

公平锁:每个线程获取锁的顺序是按照线程访问锁的先后顺序获取的,最前面的线程总是最先获取到锁。这就好像上高速排队过收费站一样,所有的车要排队等待通行,最先来的车最先通过收费站。

性能对比

公平锁和非公平锁的性能测试结果如下,以下测试数据来自于《Java并发编程实战》:

从上述结果可以看出,使用非公平锁的吞吐率(单位时间内成功获取锁的平均速率)要比公平锁高很多。

性能分析

以上测试数据虽然说明了结果,但并不能说明为什么非公平锁的性能会更高?所以,接下来,我们通过分析公平锁和非公平的执行流程,来得到这个问题的答案。

公平锁执行流程

获取锁时,先将线程自己添加到等待队列的队尾并休眠,当某线程用完锁之后,会去唤醒等待队列中队首的线程尝试去获取锁,锁的使用顺序也就是队列中的先后顺序,在整个过程中,线程会从运行状态切换到休眠状态,再从休眠状态恢复成运行状态,但线程每次休眠和恢复都需要从用户态转换成内核态,而这个状态的转换是比较慢的,所以公平锁的执行速度会比较慢。

用户态 & 内核态

用户态(User Mode):当进程在执行用户自己的代码时,则称其处于用户运行态。内核态(Kernel Mode):当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态,此时处理器处于特权级最高的内核代码中执行。

为什么分内核态和用户态?

假设没有内核态和用户态之分,程序就可以随意读写硬件资源了,比如随意读写和分配内存,这样如果程序员一不小心将不适当的内容写到了不该写的地方,很可能就会导致系统崩溃。

而有了用户态和内核态的区分之后,程序在执行某个操作时会进行一系列的验证和检验之后,确认没问题之后才可以正常的操作资源,这样就不会担心一不小心就把系统搞坏的情况了,也就是有了内核态和用户态的区分之后可以让程序更加安全的运行,但同时两种形态的切换会导致一定的性能开销。

非公平锁执行流程

当线程获取锁时,会先通过 CAS 尝试获取锁,如果获取成功就直接拥有锁,如果获取锁失败才会进入等待队列,等待下次尝试获取锁。这样做的好处是,获取锁不用遵循先到先得的规则,从而避免了线程休眠和恢复的操作,这样就加速了程序的执行效率。

比如前几天磊哥去一个小营业厅办理网络移机的业务,去了之后发现前面有人在办业务,于是磊哥就告诉前面(办理业务)的小姐姐,“我门口休息一下,您等会办理完业务,麻烦去门口叫一下我”,小姐姐人也比较好,一口就答应下来了。

但在小姐姐办完业务之后叫我,和我回到柜台办理业务之间,是有一段空闲时间的,这和等待队列中的线程被唤醒和恢复执行之间是有一段空闲时间是一样的,而在这个空闲的时间中,营业厅又来了一个老李头来交话费,等老李交完话费,我恰好也刚回来可以直接办理业务了,这样就是一个“三赢”的局面。

老李头不用排在我后面等着缴话费,我也不用等老李头交完话费再办理移机,而且在单位时间内提高了营业员办理业务的效率,她也能早早的回家,这就是所谓的“三赢”。在更短的时间内执行更多的任务,这就是非公平锁的优势

总结

本文我们介绍了公平锁和非公平锁的定义以及执行流程,从二者执行流程的细节可以看出,非公平锁因为不用按(顺)序执行,所以后来的锁也可以直接尝试获得锁,没有了阻塞和恢复执行的步骤,所以它的性能会更高。

本系列原创文章推荐

1.线程的故事:我的3位母亲成就了优秀的我!

2.线程池的7种创建方式,强烈推荐你用它...

3.轻量级锁一定比重量级锁快吗?

4.这样终止线程,竟然会导致服务宕机?

5.漫画:如何证明sleep不释放锁,而wait释放锁?

6.池化技术到达有多牛?看了这个对比吓我一跳!

7.求求你,别再用wait和notify了!

8.Semaphore自白:限流器用我就对了!

9.CountDownLatch:别浪,等人齐再团!

10.CyclicBarrier:人齐了,老司机就发车了!

11.Java中用户线程和守护线程区别这么大?

12.ThreadLocal不好用?那是你没用对!

13.ThreadLocal内存溢出代码演示和原因分析!

14.SimpleDateFormat线程不安全的5种解决方案!

15.synchronized 加锁 this 和 class 的区别!

16.synchronized 优化手段之锁膨胀机制!

17.synchronized 中的 4 个优化,你知道几个?

18.ReentrantLock 中的 4 个坑!


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

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

相关文章

java timezone_Java TimeZone setDefault()方法与示例

java timezoneTimeZone类的setDefault()方法 (TimeZone Class setDefault() method) setDefault() method is available in java.util package. setDefault()方法在java.util包中可用。 setDefault() method is used to assign the default time zone which is retrieved by us…

5.2 测试计划和估算

5.2 测试计划和估算 2015-06-23 5.2.2. 测试计划活动(K3) 对整个系统或部分系统可能的测试计划活动包括: 确定测试的范围和风险,明确测试的目标;定义测试的整体方法(测试策略),包括测…

Android 模拟器调试的缺点

1.模拟器调试速度太慢,不能清晰真实反映开发中的问题。 2.安卓定制化现象严重,模拟器达不到真机的真实水平,如控件样式、分辨率。 3.模拟器不能模拟所有的API,如Email、电话、短信、横竖屏、GPS、蓝牙、多点触控、震动、服务等基…

java timezone_Java TimeZone getDefault()方法与示例

java timezoneTimeZone类的getDefault()方法 (TimeZone Class getDefault() method) getDefault() method is available in java.util package. getDefault()方法在java.util包中可用。 getDefault() method is used to return the default time zone for this host. getDefaul…

死锁的 4 种排查工具 !

作者 | 王磊来源 | Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG_Stone死锁(Dead Lock)指的是两个或两个以上的运算单元(进程、线程或协程),都在等待…

搜索百度百科官方创建入口,怎么创建更新公司的百度百科词条呢?

在百度搜索百度百科找到百度百科官方创建入口,可以上传并创建公司类的百度百科词条,创建词条后还可以再修改更新百科词条,最终完善好的百度百科词条将会在百度上获得大量曝光。那么百度百科可以怎么创建,下面洛希爱做百科网把十多…

【HM】第2课:JavaScript基础

<pre>day02第一天的内容&#xff1a;*html标签里面的表单标签*html标签里面的表格标签思维导图1、JavaScript的简介* 什么是JavaScript&#xff1a;js是一个基于对象和事件驱动的语言&#xff0c;应用客户端。**基于对象&#xff1a;在java里面如果使用对象需要创建&…

Nginx For Windows 关于 worker_connections 不生效问题

○、结论 Nginx For Windows 建议使用 http://nginx-win.ecsds.eu/ 下载 nginx 1.17.0.1 Crow 一、起因 项目中有一个 API 服务&#xff0c;对客户端通信进行支持&#xff0c;大概 1w 客户端&#xff0c;每分钟都会进行通信。 高峰期的时候服务负载较高&#xff0c;为了防…

你没有见过的 7 种 for 循环优化,超好用!

来源&#xff1a;blog.csdn.net/csdn_aiyang/article/details/75162134我们都经常使用一些循环耗时计算的操作&#xff0c;特别是for循环&#xff0c;它是一种重复计算的操作&#xff0c;如果处理不好&#xff0c;耗时就比较大&#xff0c;如果处理书写得当将大大提高效率&…

java valueof_Java Short类valueOf()方法及示例

java valueofSyntax: 句法&#xff1a; public static Short valueOf (short value);public static Short valueOf (String value);public static Short valueOf (String value, int radixs);简短的类valueOf()方法 (Short class valueOf() method) valueOf() method is avail…

死锁终结者:顺序锁和轮询锁!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone死锁&#xff08;Dead Lock&#xff09;指的是两个或两个以上的运算单元&#xff08;进程、线程或协程&#xff09;&#xff0c;都在等待…

Nginx For Windows HTTP转发和负载

Nginx For Windows HTTP转发和负载一、需求说明二、配置文件一、需求说明 使用Nginx进行端口转发&#xff0c;并且负载到两台服务器的服务上。 监控本地服务器的 9099 端口&#xff0c;转发并负载到 127.0.0.1:9001 和 127.0.0.1:9002 服务上。&#xff08;可以选择只转发到一…

Java PushbackReader mark()方法与示例

PushbackReader类mark()方法 (PushbackReader Class mark() method) mark() method is available in java.io package. mark()方法在java.io包中可用。 mark() method is used to mark the current position in this stream and this method throws an exception during the ca…

轮询锁使用时遇到的问题与解决方案!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone当我们遇到死锁之后&#xff0c;除了可以手动重启程序解决之外&#xff0c;还可以考虑是使用顺序锁和轮询锁&#xff0c;这部分的内容可以…

DHCP 日志分析

DHCP 日志分析 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;是一种有效的IP 地址分配手段&#xff0c;现已经被广泛地应用在各种局域网管理。它能动态地向网络中每台计算机分配唯一的IP 地址&#xff0c;并提供安全、可靠、简…

Nginx For Windows Socket 端口转发

Nginx For Windows Socket 端口转发一、需求说明二、配置文件一、需求说明 使用Nginx进行端口转发 Socket 端口通信。 监控本地服务器的 3001 端口&#xff0c;转发到 10.73.60.48:3001 服务器上的 Socket 端口服务。 二、配置文件 完整配置文件如下&#xff0c;测试可用 #…

16 条 yyds 的代码规范

作者 | 涛姐涛哥链接 | cnblogs.com/taojietaoge/p/11575376.html背景&#xff1a;如何更规范化编写Java 代码的重要性想必毋需多言&#xff0c;其中最重要的几点当属提高代码性能、使代码远离Bug、令代码更优雅。一、MyBatis 不要为了多个查询条件而写 1 1当遇到多个查询条件…

linkedhashset_Java LinkedHashSet clear()方法与示例

linkedhashsetLinkedHashSet类的clear()方法 (LinkedHashSet Class clear() method) clear() method is available in java.util package. clear()方法在java.util包中可用。 clear() method is used to clear all of the existing objects in this LinkedHashSet. clear()方法…

C# 导出word文档及批量导出word文档(3)

在初始化WordHelper时&#xff0c;要获取模板的相对路径。获取文档的相对路径多个地方要用到&#xff0c;比如批量导出时要先保存文件到指定路径下&#xff0c;再压缩打包下载&#xff0c;所以专门写了个关于获取文档的相对路径的类。 1 #region 获取文档的相对路径2 pub…

Nginx For Windows 路由配置

Nginx For Windows 路由配置一、路由配置说明二、需求说明三、配置文件一、路由配置说明 使用Nginx进行路由配置。 使用过 SpringCloud 网关的同学都知道&#xff0c;网关可以使用同一IP地址、同一端口号、不同的服务ID&#xff0c;转发不同服务API信息&#xff0c;不会出现跨…