Java concurrency之非公平锁_动力节点Java学院整理
发布时间 - 2026-01-11 01:50:50 点击率:次获取非公平锁(基于JDK1.7.0_40)

非公平锁和公平锁在获取锁的方法上,流程是一样的;它们的区别主要表现在“尝试获取锁的机制不同”。简单点说,“公平锁”在每次尝试获取锁时,都是采用公平策略(根据等待队列依次排序等待);而“非公平锁”在每次尝试获取锁时,都是采用的非公平策略(无视等待队列,直接尝试获取锁,如果锁是空闲的,即可获取状态,则获取锁)。
1. lock()
lock()在ReentrantLock.java的NonfairSync类中实现,它的源码如下:
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
说明:
lock()会先通过compareAndSet(0, 1)来判断“锁”是不是空闲状态。是的话,“当前线程”直接获取“锁”;否则的话,调用acquire(1)获取锁。
(01) compareAndSetState()是CAS函数,它的作用是比较并设置当前锁的状态。若锁的状态值为0,则设置锁的状态值为1。
(02) setExclusiveOwnerThread(Thread.currentThread())的作用是,设置“当前线程”为“锁”的持有者。
“公平锁”和“非公平锁”关于lock()的对比
- 公平锁 -- 公平锁的lock()函数,会直接调用acquire(1)。
- 非公平锁 -- 非公平锁会先判断当前锁的状态是不是空闲,是的话,就不排队,而是直接获取锁。
2. acquire()
acquire()在AQS中实现的,它的源码如下:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
(01) “当前线程”首先通过tryAcquire()尝试获取锁。获取成功的话,直接返回;尝试失败的话,进入到等待队列依次排序,然后获取锁。
(02) “当前线程”尝试失败的情况下,会先通过addWaiter(Node.EXCLUSIVE)来将“当前线程”加入到"CLH队列(非阻塞的FIFO队列)"末尾。
(03) 然后,调用acquireQueued()获取锁。在acquireQueued()中,当前线程会等待它在“CLH队列”中前面的所有线程执行并释放锁之后,才能获取锁并返回。如果“当前线程”在休眠等待过程中被中断过,则调用selfInterrupt()来自己产生一个中断。
“公平锁”和“非公平锁”关于acquire()的对比
公平锁和非公平锁,只有tryAcquire()函数的实现不同;即它们尝试获取锁的机制不同。这就是我们所说的“它们获取锁策略的不同所在之处”!
非公平锁的tryAcquire()在ReentrantLock.java的NonfairSync类中实现,源码如下:
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
nonfairTryAcquire()在ReentrantLock.java的Sync类中实现,源码如下:
final boolean nonfairTryAcquire(int acquires) {
// 获取“当前线程”
final Thread current = Thread.currentThread();
// 获取“锁”的状态
int c = getState();
// c=0意味着“锁没有被任何线程锁拥有”
if (c == 0) {
// 若“锁没有被任何线程锁拥有”,则通过CAS函数设置“锁”的状态为acquires。
// 同时,设置“当前线程”为锁的持有者。
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
// 如果“锁”的持有者已经是“当前线程”,
// 则将更新锁的状态。
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
说明:
根据代码,我们可以分析出,tryAcquire()的作用就是尝试去获取锁。
(01) 如果“锁”没有被任何线程拥有,则通过CAS函数设置“锁”的状态为acquires,同时,设置“当前线程”为锁的持有者,然后返回true。
(02) 如果“锁”的持有者已经是当前线程,则将更新锁的状态即可。
(03) 如果不术语上面的两种情况,则认为尝试失败。
“公平锁”和“非公平锁”关于tryAcquire()的对比
公平锁和非公平锁,它们尝试获取锁的方式不同。
公平锁在尝试获取锁时,即使“锁”没有被任何线程锁持有,它也会判断自己是不是CLH等待队列的表头;是的话,才获取锁。
而非公平锁在尝试获取锁时,如果“锁”没有被任何线程持有,则不管它在CLH队列的何处,它都直接获取锁。
释放非公平锁(基于JDK1.7.0_40)
非公平锁和公平锁在释放锁的方法和策略上是一样的。
总结
公平锁和非公平锁的区别,是在获取锁的机制上的区别。表现在,在尝试获取锁时 —— 公平锁,只有在当前线程是CLH等待队列的表头时,才获取锁;而非公平锁,只要当前锁处于空闲状态,则直接获取锁,而不管CLH等待队列中的顺序。
只有当非公平锁尝试获取锁失败的时候,它才会像公平锁一样,进入CLH等待队列排序等待。
# Java
# 非公平锁
# concurrency
# Java线程公平锁和非公平锁的差异讲解
# java 线程公平锁与非公平锁详解及实例代码
# java非公平锁知识点实例详解
# 都是
# 会先
# 类中
# 它在
# 而非
# 值为
# 则将
# 是在
# 也会
# 就不
# 这就是
# 是一样的
# 之处
# 两种
# 我们可以
# 会像
# 过程中
# 情况下
# 简单点
# 直接调用
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何在万网开始建站?分步指南解析
Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知
如何基于云服务器快速搭建网站及云盘系统?
Laravel如何生成API文档?(Swagger/OpenAPI教程)
Laravel如何使用Eloquent进行子查询
使用豆包 AI 辅助进行简单网页 HTML 结构设计
Laravel怎么配置S3云存储驱动_Laravel集成阿里云OSS或AWS S3存储桶【教程】
Laravel如何升级到最新的版本_Laravel版本升级流程与兼容性处理
Laravel如何实现模型的全局作用域?(Global Scope示例)
javascript中的try catch异常捕获机制用法分析
微信小程序 配置文件详细介绍
Laravel如何实现本地化和多语言支持?(i18n教程)
详解jQuery中的事件
Win11怎么开启自动HDR画质_Windows11显示设置HDR选项
为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】
Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
如何快速配置高效服务器建站软件?
Android GridView 滑动条设置一直显示状态(推荐)
HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】
Laravel如何设置自定义的日志文件名_Laravel根据日期或用户ID生成动态日志【技巧】
通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】
西安专业网站制作公司有哪些,陕西省建行官方网站?
公司网站制作价格怎么算,公司办个官网需要多少钱?
如何安全更换建站之星模板并保留数据?
Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】
微信小程序 input输入框控件详解及实例(多种示例)
网站页面设计需要考虑到这些问题
Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程
如何基于云服务器快速搭建个人网站?
如何注册花生壳免费域名并搭建个人网站?
Python面向对象测试方法_mock解析【教程】
Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】
Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】
消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
Laravel如何使用Vite进行前端资源打包?(配置示例)
南京网站制作费用,南京远驱官方网站?
如何在阿里云域名上完成建站全流程?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
如何使用 jQuery 正确渲染 Instagram 风格的标签列表
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
Laravel事件监听器怎么写_Laravel Event和Listener使用教程
Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制
音响网站制作视频教程,隆霸音响官方网站?
企业网站制作这些问题要关注
简单实现Android验证码
Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程
jQuery中的100个技巧汇总
如何选择可靠的免备案建站服务器?

