常见锁的分类
入职体验:
今天运维岗位刚入职,但是目前还没有办理入职手续,但是领导发了一堆资料!看了一下,非常多的新东西,只能说努力一把!!!
一、锁的分类
1.1 可重入锁、不可重入锁
Java中提供的synchronized,ReentrantLock,ReentrantReadWriteLock都是可重入锁。
重入:当前线程获取到A锁,在获取之后尝试再次获取A锁是可以直接拿到的。
不可重入:当前线程获取到A锁,在获取之后尝试再次获取A锁,无法获取到的,因为A锁被当前线程占用着,需要等待自己释放锁再获取锁。
1.2 乐观锁、悲观锁
Java中提供的synchronized,ReentrantLock,ReentrantReadWriteLock都是悲观锁。
Java中提供的CAS操作,就是乐观锁的一种实现。
悲观锁:获取不到锁资源时,会将当前线程挂起(进入BLOCKED、WAITING),线程挂起会涉及到用户态和内核的太的切换,而这种切换是比较消耗资源的。
-
用户态:JVM可以自行执行的指令,不需要借助操作系统执行。
-
内核态:JVM不可以自行执行,需要操作系统才可以执行。
乐观锁:获取不到锁资源,可以再次让CPU调度,重新尝试获取锁资源。
Atomic原子性类中,就是基于CAS乐观锁实现的。
1.3 公平锁、非公平锁
Java中提供的synchronized只能是非公平锁。
Java中提供的ReentrantLock,ReentrantReadWriteLock可以实现公平锁和非公平锁
公平锁:线程A获取到了锁资源,线程B没有拿到,线程B去排队,线程C来了,锁被A持有,同时线程B在排队。直接排到B的后面,等待B拿到锁资源或者是B取消后,才可以尝试去竞争锁资源。
非公平锁:线程A获取到了锁资源,线程B没有拿到,线程B去排队,线程C来了,先尝试竞争一波
-
拿到锁资源:开心,插队成功。
-
没有拿到锁资源:依然要排到B的后面,等待B拿到锁资源或者是B取消后,才可以尝试去竞争锁资源。
1.4 互斥锁、共享锁
Java中提供的synchronized、ReentrantLock是互斥锁。
Java中提供的ReentrantReadWriteLock,有互斥锁也有共享锁。
互斥锁:同一时间点,只会有一个线程持有者当前互斥锁。
共享锁:同一时间点,当前共享锁可以被多个线程同时持有。
二、深入synchronized
2.1 类锁、对象锁
synchronized的使用一般就是同步方法和同步代码块。
synchronized的锁是基于对象实现的。
如果使用同步方法
-
static:此时使用的是当前类.class作为锁(类锁)
-
非static:此时使用的是当前对象做为锁(对象锁)
public class MiTest { public static void main(String[] args) {// 锁的是,当前Test.classTest.a(); Test test = new Test();// 锁的是new出来的test对象test.b();} } class Test{public static synchronized void a(){System.out.println("1111");} public synchronized void b(){System.out.println("2222");} }
2.2 synchronized的优化
在JDK1.5的时候,Doug Lee推出了ReentrantLock,lock的性能远高于synchronized,所以JDK团队就在JDK1.6中,对synchronized做了大量的优化。
锁消除:在synchronized修饰的代码中,如果不存在操作临界资源的情况,会触发锁消除,你即便写了synchronized,他也不会触发。
public synchronized void method(){// 没有操作临界资源// 此时这个方法的synchronized你可以认为木有~~ }
锁膨胀:如果在一个循环中,频繁的获取和释放做资源,这样带来的消耗很大,锁膨胀就是将锁的范围扩大,避免频繁的竞争和获取锁资源带来不必要的消耗。
public void method(){for(int i = 0;i < 999999;i++){synchronized(对象){
}}// 这是上面的代码会触发锁膨胀synchronized(对象){for(int i = 0;i < 999999;i++){
}}
}
锁升级:ReentrantLock的实现,是先基于乐观锁的CAS尝试获取锁资源,如果拿不到锁资源,才会挂起线程。synchronized在JDK1.6之前,完全就是获取不到锁,立即挂起当前线程,所以synchronized性能比较差。
synchronized就在JDK1.6做了锁升级的优化
-
无锁、匿名偏向:当前对象没有作为锁存在。
-
偏向锁:如果当前锁资源,只有一个线程在频繁的获取和释放,那么这个线程过来,只需要判断,当前指向的线程是否是当前线程 。
-
如果是,直接拿着锁资源走。
-
如果当前线程不是我,基于CAS的方式,尝试将偏向锁指向当前线程。如果获取不到,触发锁升级,升级为轻量级锁。(偏向锁状态出现了锁竞争的情况)
-
-
轻量级锁:会采用自旋锁的方式去频繁的以CAS的形式获取锁资源(采用的是自适应自旋锁)
-
如果成功获取到,拿着锁资源走
-
如果自旋了一定次数,没拿到锁资源,锁升级。
-
-
重量级锁:就是最传统的synchronized方式,拿不到锁资源,就挂起当前线程。(用户态&内核态)
2.3 synchronized实现原理
synchronized是基于对象实现的。
先要对Java中对象在堆内存的存储有一个了解。
展开MarkWord
MarkWord中标记着四种锁的信息:无锁、偏向锁、轻量级锁、
2.4 synchronized的锁升级
为了可以在Java中看到对象头的MarkWord信息,需要导入依赖
<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.9</version>
</dependency>
锁默认情况下,开启了偏向锁延迟。
偏向锁在升级为轻量级锁时,会涉及到偏向锁撤销,需要等到一个安全点(STW),才可以做偏向锁撤销,在明知道有并发情况,就可以选择不开启偏向锁,或者是设置偏向锁延迟开启
因为JVM在启动时,需要加载大量的.class文件到内存中,这个操作会涉及到synchronized的使用,为了避免出现偏向锁撤销操作,JVM启动初期,有一个延迟4s开启偏向锁的操作
如果正常开启偏向锁了,那么不会出现无锁状态,对象会直接变为匿名偏向
public static void main(String[] args) throws InterruptedException {Thread.sleep(5000);Object o = new Object();System.out.println(ClassLayout.parseInstance(o).toPrintable());
new Thread(() -> {
synchronized (o){//t1 - 偏向锁System.out.println("t1:" + ClassLayout.parseInstance(o).toPrintable());}}).start();//main - 偏向锁 - 轻量级锁CAS - 重量级锁synchronized (o){System.out.println("main:" + ClassLayout.parseInstance(o).toPrintable());}
}
整个锁升级状态的转变:
Lock Record以及ObjectMonitor存储的内容
2.5 重量锁底层ObjectMonitor
需要去找到openjdk,在百度中直接搜索openjdk,第一个链接就是
找到ObjectMonitor的两个文件,hpp,cpp
先查看核心属性:jdk8u/jdk8u/hotspot: 69087d08d473 src/share/vm/runtime/objectMonitor.hpp
ObjectMonitor() {_header = NULL; // header存储着MarkWord_count = 0; // 竞争锁的线程个数_waiters = 0, // wait的线程个数_recursions = 0; // 标识当前synchronized锁重入的次数_object = NULL;_owner = NULL; // 持有锁的线程_WaitSet = NULL; // 保存wait的线程信息,双向链表_WaitSetLock = 0 ;_Responsible = NULL ;_succ = NULL ;_cxq = NULL ; // 获取锁资源失败后,线程要放到当前的单向链表中FreeNext = NULL ;_EntryList = NULL ; // _cxq以及被唤醒的WaitSet中的线程,在一定机制下,会放到EntryList中_SpinFreq = 0 ;_SpinClock = 0 ;OwnerIsThread = 0 ;_previous_owner_tid = 0;}
适当的查看几个C++中实现的加锁流程
jdk8u/jdk8u/hotspot: 69087d08d473 src/share/vm/runtime/objectMonitor.cpp
TryLock
int ObjectMonitor::TryLock (Thread * Self) {for (;;) {// 拿到持有锁的线程void * own = _owner ;// 如果有线程持有锁,告辞if (own != NULL) return 0 ;// 说明没有线程持有锁,own是null,cmpxchg指令就是底层的CAS实现。if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {// 成功获取锁资源return 1 ;}// 这里其实重试操作没什么意义,直接返回-1if (true) return -1 ;}
}
try_entry
bool ObjectMonitor::try_enter(Thread* THREAD) {// 在判断_owner是不是当前线程if (THREAD != _owner) {// 判断当前持有锁的线程是否是当前线程,说明轻量级锁刚刚升级过来的情况if (THREAD->is_lock_owned ((address)_owner)) {_owner = THREAD ;_recursions = 1 ;OwnerIsThread = 1 ;return true;}// CAS操作,尝试获取锁资源if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {// 没拿到锁资源,告辞return false;}// 拿到锁资源return true;} else {// 将_recursions + 1,代表锁重入操作。_recursions++;return true;}
}
enter(想方设法拿到锁资源,如果没拿到,挂起扔到_cxq单向链表中)
void ATTR ObjectMonitor::enter(TRAPS) {// 拿到当前线程Thread * const Self = THREAD ;void * cur ;// CAS走你,cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;if (cur == NULL) {// 拿锁成功return ;}// 锁重入操作if (cur == Self) {// TODO-FIXME: check for integer overflow! BUGID 6557169._recursions ++ ;return ;}//轻量级锁过来的。if (Self->is_lock_owned ((address)cur)) {_recursions = 1 ;_owner = Self ;OwnerIsThread = 1 ;return ;}
// 走到这了,没拿到锁资源,count++Atomic::inc_ptr(&_count);
for (;;) {jt->set_suspend_equivalent();// 入队操作,进到cxq中EnterI (THREAD) ;if (!ExitSuspendEquivalent(jt)) break ;_recursions = 0 ;_succ = NULL ;exit (false, Self) ;jt->java_suspend_self();}}// count--Atomic::dec_ptr(&_count);}
EnterI
for (;;) {// 入队node._next = nxt = _cxq ;// CAS的方式入队。if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ;
// 重新尝试获取锁资源if (TryLock (Self) > 0) {assert (_succ != Self , "invariant") ;assert (_owner == Self , "invariant") ;assert (_Responsible != Self , "invariant") ;return ;}
}
相关文章:
常见锁的分类
入职体验: 今天运维岗位刚入职,但是目前还没有办理入职手续,但是领导发了一堆资料!看了一下,非常多的新东西,只能说努力一把!!! 一、锁的分类 1.1 可重入锁、不可重入锁…...
vue 鼠标划入划出多传一个参数
// item可以传递弹窗显示数据, $event相关参数可以用来做弹窗定位用 mouseover"handleMouseOver($event, item)" mouseleave"handleMouseLeave($event, item)"举个栗子: 做一个hover提示弹窗组件(用的vue3框架 less插件) 可以将组件…...
svn项目同步到gitLab
安装git 确保安装了git 新建一个文件夹svn-git 在文件夹中新建userinfo.txt文件,映射svn用户,这个文件主要是用于将SVN用户映射为Git用户(昵称及其邮箱)。 userinfo.txt具体格式如下: admin admin <admin163.com> lis…...
图解Dubbo,Dubbo 服务治理详解
目录 一、介绍1、介绍 Dubbo 服务治理的基本概念和重要性2、阐述 Dubbo 服务治理的实现方式和应用场景 二、Dubbo 服务治理的原理1、Dubbo 服务治理的架构设计2、Dubbo 服务治理的注册与发现机制3、Dubbo 服务治理的负载均衡算法 三、Dubbo 服务治理的实现方式1、基于 Docker 容…...
Css 如何取消a链接点击时的背景颜色
要取消 <a> 链接点击时的背景颜色,可以使用 CSS 的伪类 :active。你可以通过为 a:active 应用 background-color 属性设置为 transparent 或者 none,来取消点击时的背景色。下面是一个示例: a:active {background-color: transparent;…...
1.16.C++项目:仿muduo库实现并发服务器之HttpContext以及HttpServer模块的设计
文章目录 一、HttpContext模块二、HttpServer模块三、HttpContext模块实现思想(一)功能(二)意义(三)接口 四、HttpServer模块实现思想(一)功能(二)意义&#…...
ABAP 新增PO计划行时 新增行交货日期默认当前最大交期
ABAP 新增PO计划行时 新增行交货日期默认当前最大交期 DATA: ls_poitem TYPE mepoitem. DATA: ls_jhh TYPE meposchedule. DATA: ls_poitemc TYPE REF TO if_purchase_order_item_mm. DATA: is_persistent TYPE mmpur_bool. DATA: lt_eket TYPE TABLE OF eket. DATA: ls_e…...
VSCode怎么创建Java项目
首先安装好Java的开发环境:JDK在VSCode中安装适用于Java开发的插件。打开VSCode,点击左侧的扩展图标,搜索并安装Java Extension Pack插件。等待安装完成后,重启VSCode生效。创建一个新的Java项目,按下Ctrl Shift P&a…...
软件工程与计算(十四)详细设计中面向对象方法下的模块化
一.面向对象中的模块 1.类 模块化是消除软件复杂度的一个重要方法,每个代码片段相互独立,这样能够提高可维护性。在面向对象方法中,代码片段最重要的类,整个类的所有代码联合起来构成独立的代码片段。 模块化希望代码片段由两部…...
商城免费搭建之java商城 开源java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c
1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…...
python教程:selenium WebDriver 中的几种等待
嗨喽,大家好呀~这里是爱看美女的茜茜呐 强制等待:sleep() import time sleep(5) #等待5秒设置固定休眠时间,单位为秒。 由python的time包提供, 导入 time 包后就可以使用。 缺点: 不智能,使用太多的sleep会影响脚本运行速度。…...
【MATLAB源码-第49期】基于蚁群算法(ACO)算法的栅格路径规划,输出最佳路径图和算法收敛曲线图。
操作环境: MATLAB 2022a 1、算法描述 蚁群算法是一种模拟自然界蚂蚁觅食行为的启发式优化算法。在蚁群系统中,通过模拟蚂蚁之间通过信息素沟通的方式来寻找最短路径。 在栅格路径规划中,蚁群算法的基本步骤如下: 1. 初始化: …...
LabVIEW生产者消费者架构
LabVIEW生产者消费者架构 生产者/消费者模式可以轻松地同时处理多个进程,同时还能以不同速率迭代。 缓冲通信 当多个进程以不同速度运行时,就适合采用进程间缓冲通信。有了足够大的缓冲区后,生产者循环可以以快于消费者循环的速度运行&…...
成都瀚网科技:如何有效运营抖店来客呢?
随着电子商务的快速发展和移动互联网的普及,越来越多的企业开始将目光转向线上销售渠道。其中,抖音成为备受关注的平台。作为中国最大的短视频社交平台之一,抖音每天吸引数亿用户,这也为企业提供了巨大的商机。那么,如…...
iMazing2.17.3免费苹果手机备份还原助手
强大的 iOS 设备管理软件不管是 iPhone、iPad 或 iPod Touch 设备,只要将 iOS 设备连接到计算机,就可以处理不同类型的数据。iMazing 功能强大、易于使用,可以帮助您安全备份任何 iPhone、iPad 或 iPod Touch,备受用户信赖。 现在…...
sql查询到了数据但是实体类个别字段为null(映射失败)
参考博客: sql查询到了数据但是实体类个别字段为null(映射失败)_sql语句查到值,加字段!null没值-CSDN博客 问题描述: 1.SQL查询到了数据,在idea调试output控制台窗口打印出SQL语句,字段有值; 2.接收实体对象字段无…...
配置VScode开发环境-CUDA编程
如果觉得本篇文章对您的学习起到帮助作用,请 点赞 关注 评论 ,留下您的足迹💪💪💪 本文主要介绍VScode下的CUDA编程配置,因此记录以备日后查看,同时,如果能够帮助到更多人…...
openGauss学习笔记-101 openGauss 数据库管理-管理数据库安全-客户端接入之用SSH隧道进行安全的TCP/IP连接
文章目录 openGauss学习笔记-101 openGauss 数据库管理-管理数据库安全-客户端接入之用SSH隧道进行安全的TCP/IP连接101.1 背景信息101.2 前提条件101.3 操作步骤 openGauss学习笔记-101 openGauss 数据库管理-管理数据库安全-客户端接入之用SSH隧道进行安全的TCP/IP连接 101.…...
STM32如何使用中断?
一:EXTI 简介 STM32F10x 外部中断/事件控制器(EXTI)包含多达 20 个用于产生事件/中断请求的边沿检测器。 EXTI 的每根输入线都可单独进行配置,以选择类型(中断或事件)和相应的触发事件(上升 沿触…...
用于物体识别和跟踪的下游任务自监督学习-2-(计算机视觉中的距离度量+损失函数)
2.4 计算机视觉中的距离度量 在深度学习和计算机视觉中,距离度量通常用于比较图像、视频或其他数据的特征或嵌入。根据具体任务和数据属性,可以使用不同类型的距离度量。下面介绍了深度学习和计算机视觉中使用的一些常见类型的距离度量。 余弦相似性距…...
热成像仪的工作原理及在工业设备状态监测中的应用
前面我们介绍过>>热分析技术在工业设备状态监测中的应用,下面我们将深入探讨热成像仪的工作原理及在工业设备状态监测中的应用。 近年来,热成像仪作为一种先进的检测工具,在工业设备状态监测领域得到了广泛的应用。热成像仪能够通过探测…...
什么是库存管理?无需Excel,2023年这几款大热库存管理软件你get了吗?
什么是库存管理?库存管理是什么意思?都有哪些好用的库存管理系统?相信这些都是大家非常关注的话题,这篇就跟大家详细唠唠什么是库存管理,都用什么系统可以进行库存管理,并且为大家盘点2023年这几款大热库存…...
c# xml 参数配置表的使用
使用简介 实际使用界面 配置表管理界面 进入 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;…...
ubuntu20.04 nerf Instant-ngp
Instant-ngp linux ubuntu 20.04 GPU RTX3050Ti Instant-ngp官方文档地址 https://github.com/NVlabs/instant-ngp 参考链接Instant-ngp linux部署及使用 - 简书 Ubuntu20.04复现instant-ngp,自建数据集,导出mesh_XINYU W的博客-CSDN博客 步骤 安装基…...
隐写术--python隐写
0x00 背景 何为隐写术? 隐写术是一类可以隐藏自己写的一些东西的方法,是一门关于信息隐藏的技巧与科学。指的是采取一些不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容的方法。 可参考 一文让你完全弄懂Stegosaurus - 知乎 本文要…...
MySQL的InnoDB存储引擎中的自适应哈希索引技术
一、自适应哈希索引的工作机制与优化策略 MySQL的InnoDB存储引擎使用了一种叫做自适应哈希索引(Adaptive Hash Indexes)的技术。在某些索引值被频繁访问的情况下,InnoDB会自动在内存中为这些值建立哈希索引,以加速查询操作。 何…...
交互设计主要做什么?新手入门必读
什么是交互设计?它涉及哪些内容?交互设计师是什么样的人群?他们到底是做什么的?他们身怀什么技能?他们工作的价值在哪里?交互设计行业的现状是怎样的?工作前景又是如何的? 如果你心…...
【深度学习实验】循环神经网络(三):门控制——自定义循环神经网络LSTM(长短期记忆网络)模型
目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. LSTM类 a.__init__(初始化) b. init_state(初始化隐藏状态) c. forward(前向传播) 2. RNNModel类 a.__init__&am…...
flutter 消息并发时处理,递归查询
收到新消息的时候执行receiveNewConversation方法 可以自己模拟一下两条数据插入,延时执行插入会话的操作 收到一条新的会话消息,先记录会话ID到列表,直到第一条处理完(插入数据库后清理这个会话ID),才处理…...
第五十八章 学习常用技能 - 查看查询缓存
文章目录 第五十八章 学习常用技能 - 查看查询缓存查看查询缓存建立索引使用调谐表工具 第五十八章 学习常用技能 - 查看查询缓存 查看查询缓存 对于 SQL(用作嵌入式 SQL 时除外),系统会生成可重用代码来访问数据,并将该代码放置…...
建设一个班级网站的具体步骤/如何做网站建设
CCNET配置文件代码1 <cruisecontrol xmlns:cb"urn:ccnet.config.builder">2 <!--项目名称-->3 <name>StartKit</name>4 <!--标示类型,有多种类型。下面为默认标示,作为每次编译时生成的日志文件的名称--&…...
网站建设视频教程最新/怎么建立网站的步骤
要通过视图更新基本表数据,必须保证视图是可更新视图,即可以在INSET、UPDATE或DELETE等语句当中使用它们。对于可更新的视图,在视图中的行和基表中的行之间必须具有一对一的关系。还有一些特定的其他结构,这类结构会使得视图不可更…...
网站设计合同/百度双十一活动
我是linux 的服务器,navicat12的客户端, 开始链接的时候需要开服务器上得对外爆漏端口 3306,方法: 添加指定需要开放的端口: firewall-cmd --add-port123/tcp --permanent 重载入添加的端口: firewall-cmd …...
公司关于网站建设的通知/营销策划师
原子性 (Atomicity) 原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做。 隔离性 (Isolation) 隔离性是指多个事务并发执行的时候,事务内部的操作与其他事务是隔离的,并发执行的…...
网站 电信已备案 联通/永久免费个人网站申请注册
问题描述 给定一个字符串,你需要从第start位开始每隔step位输出字符串对应位置上的字符。 输入格式 第一行一个只包含小写字母的字符串。 第二行两个非负整数start和step,意义见上。 输出格式 一行,表示对应输出。 样例输入 abcdefg 2 2 样例…...
宁波奢华做网站排名/seo外包
Java 实例 - 获取异常的堆栈信息以下实例演示了使用异常类的 printStack() 方法来获取堆栈信息:/*author by w3cschool.ccMain.java*/public class Main{public static void main (String args[]){int array[]{20,20,40};int num115,num210;int result10;try{result…...