瞎扯之synchronized

news2024/10/1 1:16:39

我是胡说八道君,鉴别一个人基础打得牢不牢,有没有这个举一反三、将学过的知识串联起来的能力,教你一个简单的方法:关键词联想法

有兴趣的童鞋也可以跟着我的思路去画一张思维导图哦!加入你自己联想道德的部分更重要

eg: 给你一个synchronized关键字,你能想到什么?

初学Java的:我知道,一个关键字嘛,一个同步锁,保证多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。一般都是用在实例方法、静态方法、代码块这些地方。字节码monitorenter moniterexit,ACCESS_SYNCHONIZED

提到锁你是不是能想到死锁?提到死锁,死锁的四个条件是什么?怎么检测死锁?怎么避免死锁?怎么处理死锁?

从初学者这里除了多线程、同步锁、线程安全、deadlock、同步方法等你还get到哪些?

急于找工作的同学:我知道,sync是悲观锁,悲观锁就是保险箱,每次看完就要上锁,生怕钱丢了,再介绍下乐观锁是什么?

再聊一下sync的锁升级过程,锁升级过程又涉及到无锁、偏向锁、自旋锁、重量级锁,说到这些是不是能想到CAS,CAS又能想到ABA、版本号。都聊到CAS了,那能不谈谈Unsafe嘛

这个图有了解的吗?

图片

说完这些,懂哥出来了:我知道,他说的很对,但是不全,锁升级是由Java对象头中的markword中的锁状态控制的,哇哇哇哇介绍一下对象头有哪些东西,聊一下这个对象头每次升级会有什么变化?原理是什么?

图片

底层是有一个Monitor的监视器对象,因为monitor对象存在于对象的对象头中,所以任意对象都能成为锁。monitor锁依赖于操作系统的Mutex lock实现,os实现线程之间的切换需要从用户态转到内核态,耗时长,1.6之后对synchronized做了优化,引入轻量级锁、偏向锁。

看完这一段,是不是能get到很多点?

再学到jvm,你会发现JMM这一节里面是不是也有相关的知识点,sync是不是保证了可见性、原子性、有序性,JMM中绕不过去的点volatile关键字,volatile是不是又能想到内存屏障这四个字,loadload、storestore、loadstore、storeload,ACC_VOLATILE是不是和前面的ACC_SYNC类似,还有什么happens-before是什么?

堆栈空间:每个线程在进入synchronized代码块时会创建一个锁记录(Lock Record)在栈帧中,用于保存锁的状态。

偏向锁:Mark Word存储的是偏向锁的线程ID

轻量级锁:Mark Word存储的是线程栈中Lock Record的指针

重量级锁:Mark Word存储的是指向堆中monitor对象的指针。

堆栈都是jvm中学到的点,他们也和sync有关联,那聊到堆栈,你可以从数据结构的方面想一下这两个数据结构都有什么特点,有哪些常见的问题?也可以从jvm的角度去想,堆里面存什么?栈里面存什么?

再回到操作系统里,synchronized的加锁和解锁操作涉及到用户态和内核态的切换,这可能会带来一些性能开销。

当一个线程尝试获取一个被其他线程持有的锁时,该线程会进入内核态,调用操作系统的内核函数来等待锁的释放。这个过程涉及了用户态到内核态的切换,也被称为上下文切换。当锁被释放后,等待的线程再次回到用户态,继续执行。

这种用户态到内核态的切换会引入一定的性能开销,因为切换过程需要保存和恢复线程的上下文信息。如果并发线程较多,频繁的用户态和内核态切换可能会影响系统的性能表现。因此,在设计并发程序时,需要考虑synchronized的使用频率和锁粒度,以减少不必要的上下文切换,从而提高性能。

因为这个原因,Java后续是不是为了提高sync的使用度,对sync进行了一个锁优化,同时也引进了一些ReentrantLock等等的类

锁粒度的概念一些人可能不了解,锁粒度是指锁的作用范围或影响范围,它决定了在何种情况下线程需要竞争锁以及锁的精细程度。锁粒度可以分为粗粒度锁和细粒度锁两种。

比如HashTable这个类,如果有两个人一个人要取1,一个人要取2,no不可以,每次的操作是锁表整个hash表,这个锁是不是粒度就很大,一次锁整张表。别人想用只能等。

图片

既然发现这样的问题了,是不是该解决,于是ConcurrentHashMap是不是就出现了,这个1.7版本是不是用了sync关键字,而且它使用了分段锁segment,下面这个图是不是很直观,当然它可能不是这样锁的,具体的你们下去再查查,这样一看是不是对这个锁的粒度来感觉了。

图片

那感觉很不错啊,那为什么1.8又改了ConcurrentHashMap呢,1.8将sync替换成了CAS好像,在原来的数组+链表的形式,引入了红黑树,那他的锁粒度好像优化到了红黑树的根结点还是具体的节点,这个太久了记不清了,反正这个锁的粒度肯定是比1.7更小。

那关于锁的粒度你还能想到什么?

MySQL是不是有很多锁呢?

我们学习的时候可以去当个串子,把你能想到的都串起来,这样就不至于面试被问到一个知识点,你只能叭叭两句就完了。

随笔,瞎扯蛋,如果你学到了,可以填写一下腾讯收集文档,如果觉得我是瞎扯,那你猜对了, 我确实在瞎扯。

图片

happy ending,希望你们昨天七夕过的快乐

图片
有木有人知道,如果我是这篇文章的原创作者,那么我在csdn上第二次发布需要点转载吗?

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

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

相关文章

金桥跨越相伴岁月 桂冠加冕爱意时光 GP芝柏表演绎浪漫七夕

两个多世纪以前,康士坦特芝勒德 (Constant Girard) 与玛莉亚柏雷戈 (Marie Perregaux) 喜结连理,两颗心灵在爱意中交织,二人将姓氏结合,创立“Girard-Perregaux”芝柏表,成为数百年来瑞士高级制表中仅有的以夫妻双人姓…

VoxWeekly|The Sandbox 生态周报|20230821

欢迎来到由 The Sandbox 发布的《VoxWeekly》。我们会在每周发布,对上一周 The Sandbox 生态系统所发生的事情进行总结。 如果你喜欢我们内容,欢迎与朋友和家人分享。请订阅我们的 Medium 、关注我们的 Twitter,并加入 Discord 社区&#xf…

idea 对JavaScript进行debug调试

文章目录 1.新增 JavaScript Debug 配置2.配置访问地址3.访问url. 打断点测试 前言 : 工作中接手别人的前端代码没有注释,看浏览器的network或者console切来切去,很麻烦,可以试试idea自带的javscript debug功能。 1.新增 JavaScript Debug 配…

基于水循环算法优化的BP神经网络(预测应用) - 附代码

基于水循环算法优化的BP神经网络(预测应用) - 附代码 文章目录 基于水循环算法优化的BP神经网络(预测应用) - 附代码1.数据介绍2.水循环优化BP神经网络2.1 BP神经网络参数设置2.2 水循环算法应用 4.测试结果:5.Matlab代…

3d max插件CG MAGIC中的蜂窝材质功能可提升效率吗?

工作中能提升效率也都是大家所想的,对于设计师的一个设计过程中,可能想怎么样可以更快呀,是哪个步骤慢了呢? 这样的结果只能说会很多,但是建模这个步骤,肯定是有多无少的。 为了让模型更加逼真&#xff0c…

Flask狼书笔记 | 04_表单

文章目录 4 表单4.1 HTML表单4.2 使用Flask-WTF4.3 处理表单数据4.4 表单进阶实践小记 4 表单 表单是和用户交互最常见的方式之一&#xff0c;本章涉及的Python包由WTForms、Flask-WTF、Flask-CKEditor。&#xff08;p104&#xff09; 4.1 HTML表单 通过<form>标签创建…

实时同步ES技术选型:Mysql+Canal+Adapter+ES+Kibana

基于之前的文章&#xff0c;精简操作而来 让ELK在同一个docker网络下通过名字直接访问Ubuntu服务器ELK部署与实践使用 Docker 部署 canal 服务实现MySQL和ES实时同步Docker部署ES服务&#xff0c;canal全量同步的时候内存爆炸&#xff0c;ES/Canal Adapter自动关闭&#xff0c…

【HTML】HTML面试知识梳理

目录 DOCTYPE&#xff08;文章类型&#xff09;head标签浏览器乱码的原因及解决常用的meta标签与SEOscript标签中defer和async的区别src&href区别HTML5有哪些更新语义化标签媒体标签表单进度条、度量器DOM查询和Web存储Canvas和SVG拖放 &#xff08;HTML5 drag API&#xf…

ReactNative 密码生成器实战

效果展示图 使用插件 Formik 负责表单校验、监听表单提交、数据校验错误信息展示 Yup 负责表单校验规则 分析页面 从上述的展示图我们可以看到的主要元素有&#xff1a;输入框、单选按钮和按钮。其中生成的密码长度不可能很大也不可能为负数和 0&#xff0c;所以我们可以限…

【第三阶段】kotlin语言内置函数with

1.with基本上和run一样&#xff0c;只是使用方式不一致 info.run、with(info) 2.with函数返回类型是根据匿名函数最后一行的类型变化而变化 with 函数里面持有的是this 3.具名操作 package Stage3fun main() {val info"kotlin"//具名操作//thisinfo 等价info传入…

言有三新书出版,《深度学习之图像识别(全彩版)》上市发行,配套超详细的原理讲解与丰富的实战案例!...

各位同学&#xff0c;今天有三来发布新书了&#xff0c;名为《深度学习之图像识别&#xff1a;核心算法与实战案例&#xff08;全彩版&#xff09;》&#xff0c;本次书籍为我写作并出版的第6本书籍。 前言 2019年5月份我写作了《深度学习之图像识别&#xff1a;核心技术与案例…

2023-8-23 堆排序

题目链接&#xff1a;堆排序 #include <iostream>using namespace std;const int N 100010;int n, m; int h[N], Size;void down(int u) {int t u;if(u * 2 < Size && h[u * 2] < h[t]) t u * 2;if(u * 2 1 < Size && h[u * 2 1] < h…

使用go语言、Python脚本搭建一个简单的chatgpt服务网站。

使用go语言、Python脚本搭建一个简单的GPT服务网站 前言 研0在暑假想提升一下自己&#xff0c;自学了go语言编程和机器学习相关学习&#xff0c;但是一味学习理论&#xff0c;终究是枯燥的&#xff0c;于是自己弄点小项目做。 在这之前&#xff0c;建议您需要掌握以下两个技…

纹波和噪声测试知识

随着开关频率和开关速度不断的提升&#xff0c;在使用开关型的DC/DC电源的时候&#xff0c;要特别关注输入输出电源的纹波。但是测量DC/DC电源的纹波和噪声没有一个行业标准。不同厂家的测试环境以及测试标准都不太一样&#xff0c;导致很多人很迷惑。这篇文章提供了一个简单可…

为什么网络互联地址设置为30位地址

对于点对点链路&#xff0c;为了节约IPv4地址&#xff0c;一般为其分配/30地址块&#xff0c;这样包含4个地址&#xff1a;最小地址作为网络地址&#xff0c;最大地址作为广播地址&#xff0c;剩余两个可分配地址&#xff0c;分配给链路两端的接口&#xff0c;这是最普遍的方法…

stm32之14.超声波测距代码

-------------------- 源码 void sr04_init(void) { GPIO_InitTypeDef GPIO_InitStructure; //打开端口B的硬件时钟&#xff0c;就是供电 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //打开端口E的硬件时钟&#xff0c;就是供电 RC…

Electron学习3 使用serialport操作串口

Electron学习3 使用serialport操作串口 一、准备工作二、 SerialPort 介绍1. 核心软件包(1) serialport(2) serialport/stream(3) serialport/bindings-cpp(4) serialport/binding-mock(5) serialport/bindings-interface 2. 解析器包3. 命令行工具 三、创建一个demo程序1. 创建…

自平衡性:保持数据结构稳定的关键

自平衡性是一种重要的数据结构属性&#xff0c;它确保在执行插入、删除等操作后&#xff0c;数据结构能够自动进行调整&#xff0c;以保持整体的平衡状态。平衡的数据结构可以提供更快的操作性能&#xff0c;避免极端情况下的低效操作&#xff0c;同时保持树或其他结构的整体稳…

【C语言】动态内存管理(malloc,free,calloc,realloc)-- 详解

一、动态内存分配 定义&#xff1a;动态内存分配 (Dynamic Memory Allocation) 就是指在程序执行的过程中&#xff0c;动态地分配或者回收存储空间的分配内存的方法。动态内存分配不像数组等静态内存分配方法那样&#xff0c;需要预先分配存储空间&#xff0c;而是由系统根据程…

JVM——类加载与字节码技术—字节码指令

2.字节码指令 2.1 入门 jvm的解释器可以识别平台无关的字节码指令&#xff0c;解释为机器码执行。 2a b7 00 01 b1 this . init&#xff08;&#xff09; return 准备了System.out对象&#xff0c;准备了参数“hello world”,准备了对象的方法println(String)V&#xff…