带你快速了解Java锁中的公平锁与非公平锁
前言
Java语言中有许多原生线程安全的数据结构,比如ArrayBlockingQueue、CopyOnWriteArrayList、LinkedBlockingQueue,它们线程安全的实现方式并非通过synchronized关键字,而是通过java.util.concurrent.locks.ReentrantLock来实现。
锁的底层实现
无论什么语言在操作系统层面锁的操作都会变成系统调用(System Call),以 Linux 为例,就是 futex 函数,可以把它理解为两个函数:futex_wait(s),对变量 s 加锁;futex_wake(s)释放 s 上的锁,唤醒其他线程。
在ReentrantLock中很明显可以看到其中同步包括两种,分别是公平的FairSync和非公平的NonfairSync。
公平锁的作用就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的;而非公平锁是允许插队的。
默认情况下ReentrantLock是通过非公平锁来进行同步的,包括synchronized关键字都是如此,因为这样性能会更好。
因为从线程进入了RUNNABLE状态,可以执行开始,到实际线程执行是要比较久的时间的。
而且,在一个锁释放之后,其他的线程会需要重新来获取锁。其中经历了持有锁的线程释放锁,其他线程从挂起恢复到RUNNABLE状态,其他线程请求锁,获得锁,线程执行,这一系列步骤。如果这个时候,存在一个线程直接请求锁,可能就避开挂起到恢复RUNNABLE状态的这段消耗,所以性能更优化。
/** * Creates an instance of {@code ReentrantLock}. * This is equivalent to using {@code ReentrantLock(false)}. */ public ReentrantLock() { sync = new NonfairSync(); }
默认状态,使用的ReentrantLock()就是非公平锁。再参考如下代码,我们知道ReentrantLock的获取锁的操作是通过装饰模式代理给sync的。
/** * Acquires the lock. * * <p>Acquires the lock if it is not held by another thread and returns * immediately, setting the lock hold count to one. * * <p>If the current thread already holds the lock then the hold * count is incremented by one and the method returns immediately. * * <p>If the lock is held by another thread then the * current thread becomes disabled for thread scheduling * purposes and lies dormant until the lock has been acquired, * at which time the lock hold count is set to one. */ public void lock() { sync.lock(); }
下面参考一下FairSync和NonfairSync对lock方法的实现:
/** * Sync object for non-fair locks */ static final class NonfairSync extends Sync { /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } } /** * Sync object for fair locks */ static final class FairSync extends Sync { final void lock() { acquire(1); } }
当使用非公平锁的时候,会立刻尝试配置状态,成功了就会插队执行,失败了就会和公平锁的机制一样,调用acquire()方法,以排他的方式来获取锁,成功了立刻返回,否则将线程加入队列,知道成功调用为止。欢迎大家关注我的公种浩【程序员追风】,2019年多家公司java面试题整理了1000多道400多页pdf文档,文章都会在里面更新,整理的资料也会放在里面。
总结
上锁的过程本身也是有时间开销的,如果操作资源的时间比上锁的时间还短建议使用非公平锁可以提高系统的吞吐率;否则就老老实实的用公平锁。
最后
欢迎大家一起交流,喜欢文章记得点个赞哟,感谢支持!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Flutter 完全手册大纲
Flutter 完全手册大纲 Flutter 极大的改变了移动开发生态系统,其作为跨平台开发的框架,覆盖了所有屏幕,包括: Android、iOS、WEB、PC,甚至未来丰富的 IoT 设备;使用 Dart 语言开发,其技术栈也融合了最新的前端开发技术思想,例如:声明式 UI、响应式编程、异步编程等,可以极大的提高开发效率。 在介绍 Flutter 的时候,除了最基本的 Flutter 环境搭建,Widget 的使用,本手册更着重讲解 Flutter 独特的开发思维:声明式 UI 的开发思维,以及 Flutter 里不得不面对的状态管理,同时为了可以对 Flutter 有更深的理解,也还会讲解 Flutter 底层架构,包括:Isolate、Thread Model、Event Loop 等。从而让读者真正了解到 Flutter 的开发思维。 本手册是目前为止有关 Flutter 最全的手册,希望读者能通过本手册掌握 Flutter 的完全开发。 本手册总共分为四篇: 1. Flutter 介绍篇 了解 Flutter 是什么,它的发展历史、特性以及未来。掌握 Flutter 的基本开...
- 下一篇
关于近期技术改造的一些思考
在过去的差不多一个半月时间里,有幸参与了订单列表的翻译工作,这个工作就做一个事情,将订单列表的实现由php语言改为java语言(类似于搬运工的工作)。在这个过程中有一些个人的感悟,沉淀下来作为个人的总结。 个人感悟亦或是总结我觉得主要是分为两大块,一块我称之为项目把控的反思,另一块我称之为技术上的反思。 关于技术改造中项目把控的反思 现状的分析 这里想强调下前人工作的重要性,我参与的技术改造属于二期,所以很多问题和隐藏的坑已经被前人很好的解决了,我们能够站在前人的肩膀上继续前进。 因为有了前人的铺路,至少在两点上我们比较有信心,第一是实际方案的选择上几乎沿用了技术改造一期定的方案;第二是心理上对技术改造过程中能够遇到的困难比较乐观,至少我们能够遇到的问题不会比一期的更多,类似于有点战略上要藐视,战术要重视的意味。 实际执行当中至少技术上我们遇到的困难跟我们预估的比较相近,没有出现预期之外的问题。 跨团队协作问题。 在这个改造过程中,由于依赖的上下游业务接口同样需要由php改造为java的实现,所以这里就需要涉及到跨团队的协作问题。 针对这种跨团队的协作,我们也借鉴了一期技术改造的经...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Mario游戏-低调大师作品
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8