并发(3)

news2024/9/30 15:35:47

目录

11.Synchronized本质上是通过什么保证线程安全的?

12.Synchronized使得同时只有一个线程可以执行,性能比较差,有什么提升的方法?

13.Synchronized由什么样的缺陷?Java Lock是怎么弥补这些缺陷的?

14.Synchronized和Lock对比,和选择?

15.Sychronized在使用时有何注意事项?


11.Synchronized本质上是通过什么保证线程安全的?

加锁和释放锁的原理

深入JVM看字节码,创建如下代码:

使用javac 命令进行编译生成.class文件

得到如下信息

关注红色方框里的monitorenter和monitorexit即可。

Monitorenter和Monitorexit指令,会让对象在执行,使其锁计数器加1或者减1.每一个对象在同一时间只与一个monitor(锁)相关联,而一个Monitor在同一时间只能被一个线程获得,一个对象在尝试获得与这个对象相关联的Monitor锁的所有权的时候,monitorenter指令会发生如下3种情况之一:

monitor计数器为0,意味着目前还没有被获得,那这个线程就会立刻获得然后把锁计数器加1,一旦+1,别的线程再想获取,就需要等待。

如果这个monitor已经拿到了这个锁的所有权,又重入了这把锁,那锁计数器就会累加,变成2,并且随着重入的次数,会一直累加。

这把锁已经被别的线程获取了,等待锁释放。

monitorexit指令:释放对于monitor的所有权,释放过程很简单,就是讲monitor的计数器减1,如果减完以后,计数器不是0,则代表刚才是重入进来的,当前线程还继续持有这把锁的所有权,如果计数器变成0,则代表当前线程不再拥有该monitor的所有权,即释放锁。

下图表现了对象,对象监视器,同步队列以及执行线程状态之间的关系:

该图可以看出,任意线程对Object的访问,首先要获得Object的监视器,如果获取失败,该线程就进入同步状态明显呈状态变为BLOCKED,当Object的监视器占有者释放后,在同步队列中得到线程就会有机会重新获取该监视器。

可重入原理:加锁次数计数器

看如下的例子

对应的字节码

上面的SynchronizedDemo中之心个案同步代码块之后紧接着再会去执行一个静态同步方法,而这个方法锁的对象依然就这个类对象,那么这个正在执行的线程还需要获取该锁吗?答案是不必的,从上图中就可以看出来,执行静态同步方法的时候就只有一条monitorexit指令,并没有monitorenter获取锁的指令。这就是锁的重入性,即在同一锁程中,线程不需要再次获取同一把锁。

Synchronized先天具有重入性。每个对象拥有一个计数器,当线程获取该对象锁后,计数器就会加1,释放锁后就会将计数器减1.

保证可见性的原理:内存模型和happens-Before

Synchronized的happens-before规则,即监视器锁规则:对同一个监视器的解锁,happen-before于该监视器的加锁。

继续来看代码:

该代码的happens-before关系如图所示:

在图中每一个箭头连接的两个节点就代表之间的Happen-Before关系,黑色的是通过程序顺序规则推导出来,红色的为监视器锁规则推导而出:线程A释放锁happens-Before线程B加锁,蓝色的则是通过程序顺序规则和监视器锁规则推测出来happens-Before关系。现在我们来重点关注2happens-Before5, 通过这个关系我们可以得出什么?

根据Happens-Before的定义中的一条:如果A Happens-Before B,则A的执行结果对B可见,并且A的执行顺序先于B。线程A先对共享变量A进行加1,由2happens-before 5关系5可知线程A的执行结果对线程B可见即线程B所读取到的a的值为1。

12.Synchronized使得同时只有一个线程可以执行,性能比较差,有什么提升的方法?

简单来说在JVM中monitorenter和monitorexit字节码依赖于底层的操作系统的Mutex Lock来实现的,但是由于使用Mutex  Lock需要将当前线程挂起来并从用户态切换到内核态来执行,这种切换的代价是非常昂贵的;然而在现实中的大部分情况下,同步方法是运行在单线程环境(无锁竞争环境)如果每次都调用Mutex  Lock那么严重的影响程序的性能。不过在Jdk1.6中对所的实现引入了大量的优化,如锁粗化(Lock Coarsening),锁消除(Lock Elimination),轻量级锁(Lightweight Locking),偏向锁(Biased Locking),适应性自旋(Adaptive Spining)等技术来减少锁操作的开销。

锁粗化(Lock Coarsening):也就是减少不必要的紧连在一起的Unlock,lock操作,将多个连续的锁扩展成一个范围更大的锁。

锁消除(Lock Elimination):通过运行时JIT编译器的逃逸分析来消除一些没有在当前同步块以外被其他线程共享的数据的锁保护,通过逃逸分析也可以在线程本地Stack上进行对象空间的分配(同时还可以减少Heap上的垃圾收集开销)。

轻量级锁(Lightweight  Locking):这种锁实现的背后基于这样一种假设,即在真实情况下我们程序中的大部分同步代码一般处于无所竞争状态(即单线程执行环境),在无锁竞争的情况下完全可以避免调用操作系统层面的重量级互斥锁,取而代之的是在monitorenter和monitorexit中只需要依靠一条CAS原子指令就可以完成锁的获取以及释放。当存在锁竞争的情况下,执行CAS指令失败的线程将调用操作系统互斥进入到阻塞状态,当锁被释放的时候被唤醒。

偏向锁(Biased  Locking):是为了在无锁竞争的情况下避免在锁获取过程中执行不必要的CAS原子指令,因为CAS原子指令虽然相对于重量级锁来说开销比较下但还是存在非常可观的本地延迟。

适应性自旋(Adaptive  Spining):当线程在获取轻量级锁的过程中执行CAS操作失败时,在进入与monitor相关联的操作系统重量级锁(mutex semaphore)前会进入忙等待(Spining)然后再次尝试,当尝试一定次数后如果仍然没有成功则调用与monitor关联的semaphore(即互斥锁)进入到阻塞状态。

13.Synchronized由什么样的缺陷?Java Lock是怎么弥补这些缺陷的?

sychronized的缺陷

1.效率低:锁的释放情况少,只有代码执行完毕或者异常结束才会释放;试图获取锁的时候不能设定超时,不能终端一个正在使用锁的线程,相对而言,Lock可以终端和设置超时。

2.不够灵活:加锁和释放的时机单一,每个所仅有一个单一的条件(某个对象),相对而言,读写锁更加灵活。

3.无法知道是否成功获得锁:相对而言,Lock可以拿到状态。

Lock解决相应问题:

Lock类这里不做过多解释,主要看里面的4个方法:

1.lock():加锁

2.unlock():解锁

3.tryLock():尝试获取锁,返回一个boolean值

4.tryLock(long,TimeUnit):尝试获取锁,可以设置超时

Synchronized只有锁只与一个条件(是否获取锁)相关联,不灵活,后来Condition与Lock的结合解决了这个问题。

多线程竞争一个锁时,其余未得到锁的线程只能不停地尝试获得锁,而不能中断。高并发的情况下会导致性能下降。ReentrantLock的lockInterruptibly()方法可以优先考虑相应终端。一个线程等待时间过长,他可以中断自己,然后ReentrantLock相应这个中断,不再让这个线程继续等待。有了这个机制,使用ReentrantLock时就不会像synchronized那样产生死锁了。

14.Synchronized和Lock对比,和选择?

存在层次上

synchronized:Java关键字,在jvm层面上

Lock:是一个接口

锁的释放

synchronized:1.以获取锁的线程执行完同步代码,释放锁2.线程执行发生异常,jvm会让线程释放锁

Lock:在finally中必须释放锁,不然容易造成线程死锁。

锁的获取

synchronized:假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待。

Lock:分情况而定,Lock有多个锁获取方式,大致就是可以尝试获得锁,线程可以不用一直等待(可以通过tryLock判断有没有锁)

锁的释放(死锁产生)

sychronized:在发生异常时候会自动释放占有的锁,因此不会出现死锁

Lock:发生异常时候,不会主动释放占有锁,必须手动unlock来释放锁,可能引起死锁的发生

锁的状态

synchronized:无法判断

Lock:可以判断

锁的类型

synchronized:可重入  不可中断  非公平

Lock:可重入  可中断  可公平(两者皆可)

性能

synchronized:少量同步

Lock:大量同步

Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)

在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReentrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReentrantLock的性能能够维持常态;

ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性那你稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock却还能维持常态。

调度

synchronizes:使用Object对象本身的wait,notify,notifyAll调度机制

Lock:可以使用Condition进行线程之间的调度

用法

synchronized:在需要同步的对象中加入此控制,

sychronized可以加载方法上,也可以加在特定代码块中,括号中表示需要锁的对象。

Lock:一般使用ReentrantLock类作为锁。在加锁和解锁处需要通过lock()和unlock()显式指出。所以一般会在finally块中写unlock()以防死锁。

底层实现

synchronized:底层使用指令码方式来控制锁的,映射成字节码指令就是增加两个指令:monitorenter和monitorexit。当线程执行遇到monitorenter指令时会尝试获取内置锁,如果获取锁则锁计数器加1,如果没有获取锁则阻塞;当遇到monitorexit指令时锁计数器减1,如果计数器为0则释放锁。

Lock:底层是CAS乐观锁,依赖AbstractQueuedSynchronized类,把所有的请求线程构成一个CLH队列。而对该队列的操作均通过Lock-Free(CAS)操作。

15.Sychronized在使用时有何注意事项?

锁对象不能为空,因为锁的信息都保存在对象头里

作用域不宜过大,影响程序执行的速度,控制范围过大,编写代码也容易出错。

避免死锁

在能选择的情况下,既不要Lock也不要Synchronized关键字,用java.util.concurrent包中各种各样的类,如果不用该包下的类,在满足业务情况下,可以使用synchronized关键,因为代码量少,避免出错。

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

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

相关文章

物联网协议Coap中Californium CoapClient解析

目录 前言 一、CoapClient对象 1、类定义 2、Client方法调用 二、发送请求 1、构建请求 2、发起请求 3、接收响应 总结 前言 在之前的博客中物联网协议Coap之Californium CoapServer解析,文中简单介绍了CoapServer的实现。在物联网开发环境中,除了…

跨平台开发教学:构建同时支持iOS和Android的教育网校APP

当下,教育行业也逐渐迎来了数字化转型的时代。构建一款支持iOS和Android的教育网校APP,不仅可以提供更好的用户体验,还能扩大应用的覆盖面,满足不同用户群体的需求。 一、选择合适的跨平台开发框架 在开始构建教育网校APP之前&a…

PPT插件-大珩助手-免费功能-特殊格式介绍

上、下标切换 直接切换选中的字符为上、下标。 大小金额 支持超大金额的大写金额转换 当前日期 本次打开文件的时间 转二维码 将当前选中的文字,转为二维码图片,并插入到PPT当前位置 特殊字符 内置常用的特殊字符,点击使用 软件介绍 …

ssm基于vue.js的购物商场的设计与实现论文

摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装购物商场软件来发挥其高效地信息处理的作用,可以…

SpringBoot配置Swagger2与Swagger3

swagger是什么? 在平时开发中,一个好的API文档可以减少大量的沟通成本,还可以帮助新加入项目的同事快速上手业务。大家都知道平时开发时,接口变化总是很多,有了变化就要去维护,也是一件比较头大的事情。尤…

开源加解密库之GmSSL

一、简介 GmSSL是由北京大学自主开发的国产商用密码开源库,实现了对国密算法、标准和安全通信协议的全面功能覆盖,支持包括移动端在内的主流操作系统和处理器,支持密码钥匙、密码卡等典型国产密码硬件,提供功能丰富的命令行工具及…

java数据结构与算法刷题-----LeetCode64. 最小路径和

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 很多人觉得动态规划很难,但它就是固定套路而已。其实动态规划只…

基于Python新闻推荐系统 大数据毕业设计 爬虫+可视化+推荐算法 vue框架+Django框架(附源码)✅

毕业设计:2023-2024年计算机专业毕业设计选题汇总(建议收藏) 毕业设计:2023-2024年最新最全计算机专业毕设选题推荐汇总 🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题&#xff…

常见的DOM操作有哪些?常见的BOM对象有哪些?DOM操作与BOM对象的区别?

常见的DOM操作有哪些? 一、DOM 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口。 它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。 任何 HTML或XML文档都…

FineBI:简介

1 介绍 FineBI 是帆软软件有限公司推出的一款商业智能(Business Intelligence)产品。 FineBI 是定位于自助大数据分析的 BI 工具,能够帮助企业的业务人员和数据分析师,开展以问题导向的探索式分析。 2 现阶段数据分析弊端 现阶…

【Java集合篇】为什么HashMap的Cap是2^n,如何保证?

为什么HashMap的Cap是2^n,如何保证? ✔️目录✔️ 为什么是2 ^ n ?✔️为什么 X %2^n X & (2^n - 1) ? ✔️如何保证✔️初始化时期保证✔️扩容时期保证 ✔️目录 ✔️ 为什么是2 ^ n ? HashMap是通过 (table.length - 1) & (key.hashCode …

swing快速入门(四十)JList、JComboBox实现列表框

注释很详细,直接上代码 新增内容 🧧1.列表的属性设置与选项监听器 🧧2.下拉框的属性设置与选项监听器 🧧3.Box中组件填充情况不符合预期的处理方法 🧧4.LIst向Vector的转化方法 源码: package swing31_40;i…

Unity中Shader序列帧动画(总结篇)

文章目录 前言一、半透明混合自定义调整1、属性面板2、SubShader中3、在片元着色器(可选)3、根据纹理情况自己调节 二、适配Build In Render Pipeline三、最终代码 前言 在前几篇文章中,我们依次解决了实现Shader序列帧动画所遇到的问题。 Unity中Shader序列图动画…

K8S集群部署解决工作节点couldn‘t get current server API group list问题

最近在自己电脑上装了VMWare Player,在上面装了两个Ubuntu虚拟机,为了方便学习云原生技术,决定在上面装一个2个节点(一个控制面,一个工作节点)的K8S集群。 参考这篇文章: Ubuntu 22.04 搭建K8…

WebStorm 创建一个Vue项目

一、下载并安装WebStorm 步骤一 步骤二 选择激活方式 激活码: I2A0QUY8VU-eyJsaWNlbnNlSWQiOiJJMkEwUVVZOFZVIiwibGljZW5zZWVOYW1lIjoiVU5JVkVSU0lEQURFIEVTVEFEVUFMIERFIENBTVBJTkFTIiwiYXNzaWduZWVOYW1lIjoiVGFvYmFv77yaSkVU5YWo5a625qG25rAIOa0uW3peS9nOWup…

MATLAB指令

01--根据数学公式进行绘制 1.绘制连续函数 ①一元函数 t0:0.1:10; y3*t2; plot(t,y) ②一元二次函数 t0:0.1:10; yt.*t; plot(t,y) 注意此处应为点乘 ③一元3次 t0:0.1:10; yt.*t.*t; plot(t,y) ④y1/t t0:0.1:10; y1./t; plot(t,y) ⑤yexp(t) t0:0.1:10; yexp(2*t); p…

实现pytorch版的mobileNetV1

mobileNet具体细节,在前面已做了分析记录:轻量化网络-MobileNet系列-CSDN博客 这里是根据网络结构,搭建模型,用于图像分类任务。 1. 网络结构和基本组件 2. 搭建组件 (1)普通的卷积组件:CBL …

光明源:智慧公厕在实际应用中作用

什么是智慧公厕呢? 智慧公厕是一种应用先进科技和智能化技术的公共卫生设施,旨在提高公厕的管理效率、服务水平以及用户体验。这类公厕整合了各种现代技术,包括实时监控系统、智能预约服务、在线反馈机制、卫生自动化技术、导航服务、电子支…

Git 常用命令详解及如何在IDEA中操作

文章目录 前言发现宝藏一、初识Git1.Git概述2. Git的功能3. Git运行图示 二、Git下载安装三、Git 代码托管服务1.常用的 Git 代码托管服务2.使用码云代码托管服务 四、Git 常用命令1.Git 全局设置2.获取Git 仓库3.工作区、暂存区、版本库 概念4.Git 工作区中文件的两种状态5.本…

视频云存储/视频智能分析平台EasyCVR在麒麟系统中无法启动该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…