JavaWeb——锁策略, cas和synchronized优化过程

news/2024/5/1 5:53:58/文章来源:https://blog.csdn.net/xh1605004242/article/details/130115477

目录

一、锁策略

1、悲观锁和乐观锁

2、轻量级锁和重量级锁

3、自旋锁和挂起等待锁

4、互斥锁和读写锁

5、可重入锁和不可重入锁

6、公平锁和非公平锁

二、cas和synchronized 优化过程

1、CAS(compare and swap)

(1)、原子类

(2)、自旋锁

2、synchronized实现策略:

(1)、锁升级


一、锁策略

1、悲观锁和乐观锁

乐观锁和悲观锁不是具体类型的锁而是指两种不同的对待加锁的态度,这两个锁面对锁冲突的态度是相反的。

  • 乐观锁:认为不存在很多的并发操作,因此不需要加锁。
  • 悲观锁:认为存在很多并发操作,因此需要加锁。

2、轻量级锁和重量级锁

重量级锁和轻量级锁是通过结果去看待加锁解锁的过程开销。做的工作多消耗资源多,做的工作少消耗资源少。因此我们会认为乐观锁是轻量级锁,悲观锁是重量级锁。

  • 重量级锁:是进入内核态的加锁逻辑,资源开销较大。
  • 轻量级锁:是纯用户态的加锁逻辑,资源开销较小。  

3、自旋锁和挂起等待锁

  • 自旋锁:是一种轻量级锁,自旋锁类是一直反复查看当前锁是否就绪,CPU不停空转会消耗大量地CPU。
  • 挂起等待锁:是一种重量级锁,该锁不会像自旋锁一样一直查看锁状态而是先去做别的事情,过一会再来看当前锁是否就绪。

4、互斥锁和读写锁

  • 互斥锁当两个线程竞争同一把锁时会产生锁冲突进而阻塞等待。
  • 读写锁:根据代码实际的逻辑进行加锁,有读锁和写锁两种锁。读锁和读锁之间不会产生锁竞争;读锁和写锁之间会产生锁竞争;写锁和写锁之间,会产生锁竞争。如果代码中读的场景多写的场景少时,读写锁相比于互斥锁优化了效率、减少了不必要的锁竞争。

5、可重入锁和不可重入锁

  • 不可重入锁:是指同一个线程对同一把锁连续加锁两次,产生了死锁。
  • 可重入锁:是指同一个线程在外层方法获取锁,进入内层方法会自动获取锁。

注ReentrantLock和Synchronized都是可重入锁。

6、公平锁和非公平锁

公平是指遵循先来后到的原则的,因此遵守先来后到就是公平锁,不遵守先来后到的就是非公平锁

例:t1,t2,t3三个线程竞争同一把锁,谁先来的谁就拿到锁的情况叫公平锁。如果三个线程随机一个拿到锁,后来的线程可能会先拿到锁的情况叫非公平锁。

  • 公平锁:指多个线程按照申请锁的顺序来获取锁。
  • 非公平锁:指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。

注:操作系统默认的锁的调度是非公平的。系统对于线程的调度是随机的,自带的synchronized这个锁是非公平的。想要实现公平锁需要在synchronized的基础上,加个队列来记录这些加锁线程的顺序。

二、cas和synchronized 优化过程

1、CAS(compare and swap)

寄存器A的值和内存K的值进行对比,如果值相同就把寄存器B的值和内存K的值进行交换

//伪代码
boolean CAS(address,exceptValue,swapValue){if(&address==exceptedValue{&address=swapValue;return true;}return false;
}

注:CAS操作是一条CPU指令(不必加锁就能够保证线程安全)并非是上述这段代码,这一条指令就能完成上述这段代码的功能。

(1)、原子类

实现原子类,标准库里提供了AtomInteger类,该类可以保证++--时的线程安全

class AtomicInteger{private int value;public int getAndIncrement(){int oldValue=value;while(CAS(value,oldValue,oldValue+1)!=true){oldValue=vlaue;}return oldValue;}
}

oldValue可以被视为寄存器,如果发现value和oldValue的值相同,此时就把oldValue+1设置到value中,相当于++,然后CAS返回true,循环结束。反之如果value和oldValue不相同,CAS什么都不做并返回false,进入循环,重新设置oldValue的值。

即:此处的CAS就是在确认当前的value是否发生过改变,如果没变过才能自增,如果变过了就先更新再自增。

例: 

之前的线程不安全是因为一个线程不能及时的感知另一个线程对内存的修改。

如:t2在自增时,先读后自增。此时在自增之前t1已经自增过了,t2是在1的基础上自增的,就出现了问题。

使用CAS之后,t2在自增前会先检查寄存器的值和内存的值是否一致

(2)、自旋锁

反复检查当前的锁状态,看锁是否解开。通过CAS看当前锁是否被某个线程持有,如果这个锁已经被别的线程持有,那么就自选等待。如果这个锁没有被别的线程持有,那么就把owner设为当前尝试加锁的线程

public class SpinLock{private Thread owner=null;public void lock(){while(!CAS(this.owner,null,Thread.currentThread()){}}public void unlock(){this.owner=null;}
}

如果当前owner是null,比较就成功,就把当前线程的引用设置到owner中,加锁完成循环结束。比较不成功意味着owner非空,锁已经有线程持有了。此时CAS就什么也不做直接返回false,循环继续进行,此时这个循环不停尝试询问锁是否释放。

好处:一旦锁释放就能立即获取锁。

坏处:消耗大量CPU资源。 

乐观锁一般情况下锁冲突概率低,实现成自旋锁比较合适。

注:CAS的关键是对比内存和寄存器的值是否相同,但这对于aba问题会有一定概率出问题。

如何解决aba问题呢?aba问题的关键是值会反复横跳

  • 可以通过约定数据只能单方向变化(只能增加或减小)
  • 也可以通过引入另一个版本号变量,约定版本号只能增加,每次修改都会增加一个版本号。而每次CAS对比时,就不是对比数值本身,而是对比版本号。

2、synchronized实现策略:

(1)、锁升级

偏向锁:

只是先让线程针对锁有一个标记。如果整个代码执行过程中都没遇到别的线程竞争这个锁,此时就不用真的加锁了。但要是有别的线程尝试来竞争这个锁,此时偏向锁就立即升级成真的锁(轻量级锁),此时别的锁只能等待。既保证了效率,又保证了线程安全。

自旋锁:

速度快但是消耗大量cpu。自旋时cpu快速空转,如果当前锁竞争激烈,多个线程都在自旋,cpu的消耗就非常大。既然如此,就升级成重量级锁,在内核中进行阻塞等待(意味着线程要暂时放弃cpu,由内核进行后续调度)

注:运行时jvm做出的优化手段,主流的jvm实现只能升级不能降级。

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

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

相关文章

路由器的两种工作模式及快速通过express搭建微型服务器流程,解决刷新页面服务端404的问题

history模式与hash模式 首先这个#叫做hash,最大的特点就是不会随的http请求,发给服务器。 默认的模式是hash模式,如果想要修改,可以在router里面的index.js中配置mode属性, 它们俩直接的区别最明面上的有没有#和hist…

类型转换——C++

1. C语言中的类型转换 在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化, C语言中总共有两种形式的类型转换:隐式类型转换…

linux工具gcc/g++/gdb/git的使用

目录 gcc/g 基本概念 指令集 函数库 (重要) gdb使用 基本概念 指令集 项目自动化构建工具make/makefile 进度条小程序 ​编辑 git三板斧 创建仓库 git add git commit git push git status git log gcc/g 基本概念 gcc/g称为编译器…

[ 应急响应基础篇 ] evtx提取安全日志 事件查看器提取安全日志

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…

Java阶段一Day22

Java阶段一Day22 文章目录Java阶段一Day22线程安全synchronized教师总结新单词多线程多线程并发安全问题概念例synchronized关键字同步方法同步块在静态方法上使用synchronized互斥锁总结重点:多线程并发安全问题聊天室(续)实现服务端发送消息给客户端服务端转发消息给所有客户…

Android FrameWork 知识点与面试题整合~

1.如何对 Android 应用进行性能分析 android 性能主要之响应速度 和UI刷新速度。 首先从函数的耗时来说,有一个工具TraceView 这是androidsdk自带的工作,用于测量函数耗时的。 UI布局的分析,可以有2块,一块就是Hierarchy Viewe…

SpringBoot集成Mybatis-Plus实现多租户动态数据源

1. 概述 最近接手一个多租户系统,多租户主要的就是租户之间的数据是相互隔离的,每个租户拥有自己独立的数据,相互之间不干扰。目前实现多租户主要有三种方案: 独立数据库 每个租户拥有自己单独的数据库,从物理上隔离了…

手写一个IO泄露监测框架

作者:长安皈故里 大家好,最近由于项目原因,对IO资源泄漏的监测进行了一番调研深入了解,发现IO泄漏监测框架实现成本比较低,效果很显著;同时由于IO监测涉及到反射,还了解到了通过一种巧妙的方式实…

通达信欧奈尔RPS指标公式详解

RPS相对强度指标,是国内的投资者根据威廉欧奈尔所著书籍《笑傲股市》中的RS评级改进的。 根据书中介绍: RS评级衡量了某一给定股票在过去52周内相对股市中其他股票的表现。市场上每一只股票都被指定了1~99范围内的某一数值,99代表相对强度最高…

YOLOV7运行步骤(推理、训练全过程)

下载源代码:点击下载 执行以下命令安装requirements.txt中的相关依赖 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple官网下载权重yolov7.pt(测试使用)、yolov7-tiny.pt(训练使用,这里…

10 JS01——初识JS

目标: 1、初识JavaScript 2、JavaScript注释 3、JavaScript输入输出语句 一、初识JavaScript 1、JavaScript是什么 JavaScript是世界上最流行的语言之一,是一种运行在客户端的脚本语言(Script是脚本的意思) 脚本语言:不需要编译,运行过程…

Vue2-黑马(九)

0目录: (1)router-动态菜单 (2)vuex-入门 (3)vuex-mapState (1)router-动态菜单 我们点击按钮跳转到主页面,主页在制作动态菜单,路由的跳转方…

keil代码格式化快捷方法

美化当前文件:-n !E --styleansi -p -s4 -S -f -xW -w -xw 美化整个工程文件:-n "$E*.c" "$E*.h" --styleansi -p -s4 -S -f -xW -w -xw -R 当前时间:!E~E^E 添加文件注释:!E 函数功能注释:!E ~…

快排(动图详细版,快速理解)

注:本文主要介绍六大排序中的快排 文章目录前言一、三大法则1.1 Hoare法1.2 挖坑法1.3 双指针法(更加便捷)1.4 三种方法时间复杂度计算二、快排栈问题优化方式2.1 三数取中2.2 小区间优化三、非递归快排前言 快速排序是Hoare于1962年提出的一…

Linux高并发服务器(webserver)

一.有限状态机 它的转移函数表示系统从一个状态转移到另一个状态的条件 二.EPOLL 在内核中创建一个数据,这个数据有两个比较重要的数据,一个是需要检测的文件描述符的信息(红黑树),一个双向链表,存放检测到…

利用多专家模型解决长尾识别任务

来源:投稿 作者:TransforMe 编辑:学姐 贡献 提出了RoutIng Diverse Experts(RIDE),不仅可以减少所有类别的variance,并且还可以减少尾部类的bias。同时提升了头部和尾部的性能。 思路 目前存…

easyrecovery2023电脑文件数据恢复软件功能介绍

EasyRecovery功能全面,即便是没有经验的小白用户也可以很快上手,让你足不出户即可搞定常见的数据丢失问题。 在使用和操作存储设备期间,数据丢失问题在所难免。比如,误删除某个文件、不小心将有数据的分区格式化、误清空了有重要…

2023“认证杯”数学中国数学建模赛题浅析

2023年认证杯”数学中国数学建模如期开赛,本次比赛与妈杯,泰迪杯时间有点冲突。因此,个人精力有限,有些不可避免地错误欢迎大家指出。为了大家更方便的选题,我将为大家对四道题目进行简要的解析,以方便大家…

【vue3】04-vue基础语法补充及阶段案例

文章目录vue基础语法补充vue的computedvue的watch侦听书籍购物车案例vue基础语法补充 vue的computed computed:用于声明要在组件实例上暴露的计算属性。(官方文档描述) 我们已经知道,在模板中可以直接通过插值语法显示一些data中…

智能网卡相关知识(smart nic 、DPU)

网卡作为穿行在网络与计算之间的桥梁,是可以解决计算瓶颈的关键硬件。 随着CPU 密度和数据中心网络带宽的进一步提升,用户对预期性能的需求,系统运行平稳性都会有更高的要求。云厂商一方面面临巨大的成本压力,另一方面面临巨大的…