wordpress文章添加版权/枫树seo网

wordpress文章添加版权,枫树seo网,wordpress查询码,强生公司营销网站为什么要这样做前言 在java 开发中对于锁的应用非常的常见,如果对于什么时候该用什么锁,以及锁实现的原理有所不知道的,或者面试过程中面试官问你不知道怎么回答的,欢迎来看下面的文章 1、synchronized和ReentrantLock的区别 2、synchronized的…

前言

在java 开发中对于锁的应用非常的常见,如果对于什么时候该用什么锁,以及锁实现的原理有所不知道的,或者面试过程中面试官问你不知道怎么回答的,欢迎来看下面的文章

1、synchronized和ReentrantLock的区别

在这里插入图片描述

2、synchronized的一些特性和底层原理的实现

2.1 synchronized 的锁升级过程

在 JVM 中,锁升级是不可逆的,即一旦锁被升级为下一个级别的锁,就无法再降级。

首先默认的无锁状态,当我们加锁以后,可能并没有多个线程去竞争锁,此时我们可以默认为只有一个线程要获取锁,即偏向锁,当锁转为偏向锁以后,被偏向的线程在获取锁的时候就不需要竞争,可以直接执行。

当确实存在少量线程竞争锁的情况时,偏向锁显然不能再继续使用了,但是如果直接调用重量级锁在轻量锁竞争的情况下并不划算,因为竞争压力不大,所以往往需要频繁的阻塞和唤醒线程,这个过程需要调用操作系统的函数去切换 CPU 状态从用户态转为核心态。因此,可以直接令等待的线程自旋,避免频繁的阻塞唤醒 ,此时升级为轻量级锁

当竞争加大时,线程往往要等待比较长的时间才能获得锁,此时在等待期间保持自旋会白白占用 CPU 时间,此时就需要升级为重量级锁,即 Monitor 锁,JVM 通过指令调用操作系统函数阻塞和唤醒线程。

2.2 synchronized的锁优化

2.2.1 自适应自旋锁

自旋锁依赖于 CAS,我们可以手动的设置 JVM 的自旋锁自旋次数,但是往往很难确定适当的自旋次数,如果自旋次数太少,那么可能会引起不必要的锁升级,而自旋次数太长,又会影响性能。在 JDK6 中,引入了自适应自旋锁的机制,对于同一把锁,当线程通过自旋获取锁成功了,那么下一次自旋次数就会增加,而相反,如果自旋锁获取失败了,那么下一次在获取锁的时候就会减少自旋次数。

2.2.2 锁消除

在一些方法中,有些加锁的代码实际上是永远不会出现锁竞争的,比如 Vector 和 Hashtable 等类的方法都使用 synchronized 修饰,但是实际上在单线程程序中调用方法,JVM 会检查是否存在可能的锁竞争,如果不存在,会自动消除代码中的加锁操作。

2.2.3 锁粗化

我们常说,锁的粒度往往越细越好,但是一些不恰当的范围可能反而引起更频繁的加锁解锁操作,比如在迭代中加锁,JVM 会检测同一个对象是否在同一段代码中被频繁加锁解锁,从而主动扩大锁范围,避免这种情况的发生。

2.3 synchronized的底层原理的实现

synchronized 意为同步,它可以用于修饰静态方法,实例方法,或者一段代码块。其中修饰代码块和方法有一点不同
它是一种可重入的对象锁。当修饰静态方法时,锁对象为类;当修饰实例方法时,锁对象为实例;当修饰代码块时,锁可以是任何非 null 的对象。由于其底层的实现机制,synchronized 的锁又称为监视器锁。

同步代码块
    public void synchronizedMethod3() {synchronized(this) {System.out.println("synchronizedMethod3");}}

反编译之后:
在这里插入图片描述

monitorenter      // 尝试获取对象锁  
...  
monitorexit       // 正常退出同步块(偏移量 15)  
goto 23  
monitorexit       // 异常退出同步块(偏移量 21)  
athrow  

这里的 monitorenter 与 monitorexit 即是线程获取 synchronized 锁的过程。

当线程试图获取对象锁的时候,根据 monitorenter 指令:

如果 Monitor 的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为 Monitor 的所有者;
如果线程已经占有该 monitor,只是重新进入,则进入 Monitor 的进入数加1(可重入); 如果其他线程已经占用了
monitor,则该线程进入阻塞状态,直到 Monitor 的进入数为0,再重新尝试获取 Monitor 的所有权; 当线程执行完以后,根据
monitorexit 指令:

当执行 monitorexit 指令后,Monitor 的进入数 -1; 如果 – 1 后 Monitor 进入数为 0,则该线程不再拥有这个锁,退出 monitor; 如果 – 1 后 Monitor 进入数仍不为0,则线程继续持有这个锁,重复上述过程直到使用完毕。

特点:

  • 显式生成 monitorenter 和 monitorexit 指令 进行获取锁和释放锁
  • 异常表中注册两个退出路径,确保锁必然释放
同步方法
public synchronized void syncMethod() {  System.out.println("同步方法");  
}  
关键字节码:flags: ACC_PUBLIC, ACC_SYNCHRONIZED  

通过 ACC_SYNCHRONIZED 标志隐式实现锁机制是 Java 中 synchronized 关键字的核心实现原理。 在 Java
虚拟机(JVM)中,synchronized 关键字修饰的方法或代码块会通过在方法的 access_flags 字段中添加
ACC_SYNCHRONIZED 标志来标识该方法为同步方法。这个标志告诉 JVM,该方法需要进行同步操作。

同步机制的隐式实现 当一个方法被标记为 ACC_SYNCHRONIZED 时,JVM 在方法调用时会隐式地执行加锁和解锁操作。具体来说:

加锁:在方法执行前,线程需要获取与该方法相关的监视器锁(monitor)。如果锁已被其他线程持有,则当前线程会被阻塞,直到锁被释放。
解锁:当方法正常完成或抛出异常时,锁会被自动释放。这确保了方法的原子性和可见性。

特点:

  • 通过 ACC_SYNCHRONIZED 标志隐式实现锁机制
  • JVM 在方法调用和返回时自动插入锁操作
实现原理

synchronized 是对象锁,在 JDK6 引入锁升级机制后,synchronized 的锁实际上分为了偏向锁、轻量级锁和重量级锁三种,这三者都依赖于对象头中 MarkWord 的数据的改变。

对象

每个 Java 对象在内存中分为 对象头(Header) 、 实例数据(Instance Data) 和 对齐填充(Padding)
在这里插入图片描述
对象头是实现锁的核心区域,其结构如下

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/758316d58cc84158bcca7804c211126d.png

其中markWord的样子如下:
在这里插入图片描述

2.3 重量级锁与监视器

synchronized 的对象锁是基于监视器对象 Monitor 实现的,而根据上文,我们知道锁信息存储于对象自己的 MarkWord 中,那么 Monitor 和 对象又是什么关系呢?

实际上,在对象在创建之初就会在 MarkWord 中关联一个 Monitor 对象 ,当锁升级到重量级锁时,markWord存储指向 Monitor 对象的指针。

Monitor 对象在 JVM 中基于 ObjectMonitor 实现,代码如下:

ObjectMonitor() {_header       = NULL;_count        = 0; // 持有锁次数_waiters      = 0,_recursions   = 0;_object       = NULL;_owner        = NULL; // 当前持有锁的线程_WaitSet      = NULL; // 等待队列,处于wait状态的线程,会被加入到_WaitSet_WaitSetLock  = 0 ;_Responsible  = NULL ;_succ         = NULL ;_cxq          = NULL ;FreeNext      = NULL ;_EntryList    = NULL ; // 阻塞队列,处于等待锁block状态的线程,会被加入到该列表_SpinFreq     = 0 ;_SpinClock    = 0 ;OwnerIsThread = 0 ;
}

ObjectMonitor 中有两个队列,_WaitSet 和 _EntryList,用来保存 ObjectWaiter 对象列表( 每个等待锁的线程都会被封装成 ObjectWaiter 对象 ),_owner 指向持有 ObjectMonitor 对象的线程,当多个线程同时访问一段同步代码时:
首先会进入 _EntryList 集合,当线程获取到对象的 Monitor 后,进入 _Owner 区域并把 monitor 中的 owner 变量设置为当前线程,同时 monitor中的计数器 count 加1;
若线程调用 wait() 方法,将释放当前持有的 monitor,owner 变量恢复为 null,count 自减1,同时该线程进入 WaitSet集合中等待被唤醒;
若当前线程执行完毕,也将释放 Monitor 并复位 count 的值,以便其他线程进入获取 Monitor;
这也解释了为什么 notify() 、notifyAll()和wait() 方法会要求在同步块中使用,因为这三个方法都需要获取 Monitor 对象,而要获取 Monitor,就必须使用 monitorenter指令。

2.4 synchronized线程调用时的阻塞场景


public class Example {public synchronized void methodA() { ... }public synchronized void methodB() { ... }
}

/线程1调用obj.methodA(),线程2调用obj.methodB() → 线程2阻塞,直到methodA释放锁
所以再用的时候尽可能的缩小锁的范围,代码块加锁

总结

每个对象在内存中分为三个部分示例数据(存放类信息)、对象头和对齐填充,其中对象头有个重要的组成部分markWord,markWord中存储一些锁相关的引用,通过markWord中的锁标志位,我们可以清楚的知道锁的级别,是重量级锁,还是轻量级锁,还是偏向锁,当是重量级锁的时候,markWord中存储了对监视器Monitor 对象的引用,synchronized 的对象锁是基于监视器对象 Monitor 实现的,在对象在创建之初就会在 MarkWord 中关联一个 Monitor 对象 ,当锁升级到重量级锁时,markWord存储指向 Monitor 对象的指针。而要获取 Monitor,就必须使用 monitorenter指令,可重入的表现是,Monitor里面有一个count,一次monitorenter后count 加1,一次monitorExit 后count减1

参考文章:https://cloud.tencent.com/developer/article/2120268?pos=comment

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

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

相关文章

Pytorch中Tensorboard的学习

1、Tensorboard介绍 TensorBoard 是 TensorFlow 开发的一个可视化工具,用于帮助用户理解和调试机器学习模型的训练过程。尽管它最初是为 TensorFlow 设计的,但通过 PyTorch 的 torch.utils.tensorboard 模块,PyTorch 用户也可以方便地使用 Te…

数据结构篇:空间复杂度和时间复杂度

目录 1.前言: 1.1 学习感悟 1.2 数据结构的学习之路(初阶) 2.什么是数据结构和算法 2.1 数据结构和算法的关系 2.2 算法的重要性 2.3 如何衡量算法的好坏 3.时间复杂度 3.1 时间复杂度的概念 3.2 大O的渐进表示法 O() 4.空间复杂度 5. 常见的时间复杂度和…

泰坦军团携手顺网旗下电竞连锁品牌树呆熊 共创电竞新纪元

在电竞行业的浪潮中,品牌之间的战略合作愈发成为推动市场前行的重要动力。最近,电竞显示器领域领军品牌泰坦军团高层领导出席顺网旗下电竞连锁品牌树呆熊十周年盛典。会议现场,双方高层领导宣布泰坦军团与树呆熊正式达成战略合作伙伴关系。 在…

信号的产生和保存

信号的产生 信号就是操作系统对用户操作做出的反应,但它的本质就是往操作系统写入信号,这是由操作系统的结构决定的。通过修改比特位来告诉操作系统接收信号和传了几号信号。 也正是因为我们身为用户无法亲自修改内核数据,所以我们需要通过操…

深度学习技术与应用的未来展望:从基础理论到实际实现

深度学习作为人工智能领域的核心技术之一,近年来引起了极大的关注。它不仅在学术界带来了革命性的进展,也在工业界展现出了广泛的应用前景。从图像识别到自然语言处理,再到强化学习和生成对抗网络(GAN),深度…

蓝光三维扫描技术:汽车零部件检测的精准高效之选

——汽车方向盘配件、保险杠塑料件、钣金件检测项目 汽车制造工业的蓬勃发展,离不开强大的零部件制造体系作支撑。汽车零部件作为汽车工业的基础,其设计水平、制造工艺、质量控制手段逐渐与国际标准接轨,对于零部件面差、孔位、圆角、特征线…

六十天前端强化训练之第三十天之深入解析Vue3电商项目:TechStore全栈实践(文结尾附有源代码)

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗,谢谢大佬! 目录 深入解析Vue3电商项目:TechStore全栈实践 一、项目架构设计 二、核心功能实现 三、组合式API深度实践 四、性能优化实践 五、项目扩展方向 六、开发经验总结…

不同机床对螺杆支撑座的要求有哪些不同?

螺杆支撑座是机械设备中重要的支撑部件,其选择直接影响到设备的稳定性和使用寿命,尤其是在机床中,不同的机床对螺杆支撑座的要求也是不同的。 1、精度:精密测量用的基准平面和精密机床机械的检验测量设备,需要使用高精…

Federated learning client selection algorithm based on gradient similarity阅读

基于梯度相似性的联邦学习客户端选择算法 Abstract 摘要introduction**背景****目的****结论****结果****讨论****思路** 链接:https://link.springer.com/article/10.1007/s10586-024-04846-0 三区 Abstract 摘要 联邦学习(FL)是一种创新的…

航天军工与金融行业 UE/UI 设计:跨越领域的体验革新之道

在数字化时代,用户体验(UE)和用户界面(UI)设计成为众多行业提升竞争力的关键因素。航天军工与金融行业虽业务性质差异巨大,但在 UE/UI 设计方面却面临着一些相似挑战,同时也在各自的探索中展现出…

【Git】--- 分支管理

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: Git 本篇博客我们来介绍Git的一个重要功能之一 ---- 分支。我们将讲解关于分支的各种操作,以及如何帮助我们进行开发。 🏠 理解分支…

Vue3前端开发:组件化设计与状态管理

Vue3前端开发:组件化设计与状态管理 一、Vue3组件化设计 组件基本概念与特点 是一款流行的JavaScript框架,它支持组件化设计,这意味着我们可以将页面分解成多个独立的组件,每个组件负责一部分功能,通过组件的嵌套和复用…

动手学深度学习11.9. Adadelta-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记,以及对课后练习的一些思考,自留回顾,也供同学之人交流参考。 本节课程地址:72 优化算法【动手学深度学习v2】_哔哩哔哩_bilibili 本节教材地址:11.9. Adadelta —…

Android Audio基础(13)——audiomixer

在 Android 平台上,音频混合器 AudioMixer 主要用在 AudioFlinger 里,将多路音频源数据混音(包括混音、音量处理、重采样及处理声道等)。位于 framework 的音频处理模库 libaudioprocessing(frameworks/av/media/libau…

Matlab教程001:软件介绍和界面使用

1.1 软件介绍 1.1.1 Matlab的介绍 MATLAB(MATrix LABoratory)是一款由 MathWorks 公司开发的高级编程语言和交互式环境,广泛用于 科学计算、数据分析、机器学习、工程建模、仿真和信号处理 等领域。 1.1.2 主要应用领域 数据分析与可视化…

毫米波雷达标定(2)

1. 前言 前面文章中介绍了产线上毫米波雷达的标定原理和流程,这篇文章则主要介绍其在线标定方法。相对于产线标定,在线标定具备使用自然场景而不是依赖特定标靶的优点,但因此其标定精度会相对差一点。在线标定一般应用于售出产品的维护场景,如果其标定结果精度可以满足使用…

Linux fority source和__builtin_xxx

这段代码是用于启用和配置 GCC/Clang 的 Fortify Source 安全机制的预处理指令。Fortify Source 主要用于在编译时增强对缓冲区溢出等内存安全问题的检查。以下是对每一部分的详细解释: 1. 最外层条件编译 # if CONFIG_FORTIFY_SOURCE > 0目的:检查…

语言模型理论基础-持续更新-思路清晰

1.预训练 相似的任务A、B,任务A已经用大数据完成了训练,得到模型A。 我们利用-特征提取模型的-“浅层参数通用”的特性,使用模型A的浅层参数,其他参数再通过任务B去训练(微调)。 2.统计语言模型 通过条件…

ResNet与注意力机制:深度学习中的强强联合

引言 在深度学习领域,卷积神经网络(CNN)一直是图像处理任务的主流架构。然而,随着网络深度的增加,梯度消失和梯度爆炸问题逐渐显现,限制了网络的性能。为了解决这一问题,ResNet(残差…

【C++】——C++11新特性

目录 前言 1.初始化列表 2.std::initializer_list 3.auto 4.decltype 5.nullptr 6.左值引用和右值引用 6.1右值引用的真面目 6.2左值引用和右值引用比较 6.3右值引用的意义 6.3.1移动构造 6.4万能引用 6.5完美转发——forward 结语 前言 C,这门在系统…