【多线程与高并发(锁)】1、锁的概念、分类和状态

1、锁的概念

java当中的锁、是在多线程环境下为保证共享资源健康、线程安全的一种手段。

线程操作某个共享资源之前,先对资源加一层锁,保证操作期间没有其他线程访问资源,当操作完成后,再释放锁。

2、锁的分类

Java中的锁按照不同的分类方式,大概可以分为如下几类:
在这里插入图片描述
以上都属于是一些锁的名称、属性。以Java来说,关于锁的大分类,就只有:悲观锁、乐观锁这两种。

  • 乐观锁: 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。
    java中的乐观锁基本都是通过CAS操作实现的,CAS是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。

  • 悲观锁:悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会block 直到拿到锁 Java 中的悲观锁就是Synchronized
    AQS 框架下的锁则是先尝试 cas 乐观锁去获取锁,获取不到,才会转换为悲观锁,如 RetreenLock

  • 自旋锁:

    • 原理: 自旋锁原理非常简单,如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需自旋,等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。
      线程自旋需消耗 cup的,如果一直获取不到锁,则线程长时间占用CPU自旋,需要设定一个自旋等待最大事件在最大等待时间内仍未获得锁就会停止自旋进入阻塞状态。
    • 优点:自旋锁尽可能的减少线程的阻塞,这对于锁的竞争不激烈,且占用锁时间非常短的代码块来说性能能大幅度的提升,因为自旋的消耗会小于线程阻塞挂起再唤醒的操作的消耗(这些操作会导致线程发生两次上下文切换)
    • 缺点:锁竞争激烈或者持有锁的线程需要长时间占用锁执行同步块,不适合使用自旋锁了,因为自旋锁在获取锁前一直都是占用 cpu
      做无用功,同时有大量线程在竞争一个锁,会导致获取锁的时间很长,线程自旋的消耗大于线程阻塞挂起操作的消耗,其它需要 cup 的线程又不能获取到cpu,造成 cpu 的浪费
  • Synchronized 同步锁:

    • synchronized 关键字,用于解决多个线程间访问资源同步性问题,保证其修饰的方法或代码块任意时刻只能有一个线程访问synchronized 它可以把任非NULL 的对象当作锁。他属于独占式悲观锁,同时属于可重入锁。
    • 作用范围:作用实例方法时。锁住的是对象的实例(this) ; 作用静态方法时,锁住的是该类,该 Class所有实例,又因为 Class的相关数据存储在永久带 PermGen(jdk1.8 则是 元空间),永久带是全局共享的,因此静态方法锁相当于类的一个全局锁,会锁所有调用该方法的线程
    • synchronized实现: synchronized是根据JVM实现的,该关键字的优化也是在JVM层面实现 而未直接暴露
      JDK1.6后对锁做了大量优化如偏向锁,轻量锁,自旋锁,自适应锁等等

3、锁的状态

锁主要有四种状态:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态,他们会随着锁竞争的激烈而逐渐升级且这种升级不可降,利用该策略提高获得锁和释放锁的效率

3.1 偏向锁

引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行路径,因为轻量级锁的获取及释放依赖多次 CAS 原子指令,而偏向锁只需要在置换ThreadID 的时候依赖一次 CAS原子指令(由于一旦出现多线程竞争的情况就必须撤销偏向锁,所以偏向锁的撤销操作的性能损耗必须小于节省下来的 CAS 原子指令的性能消耗)。
轻量级锁是为了在线程交替执行同步块时提高性能,而偏向锁则是在只有一个线程执行同步块时进一步提高性能。

3.2 轻量级锁(CAS+自旋锁)

CAS (Compare And Swap, 在进行比较后如果满足条件,就会交换内容)。
“轻量级” 是相对于使用操作系统互斥量来实现的传统锁而言的。
轻量级锁并不是用来代替重量级锁的,它的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用产生的性能消耗。
轻量级锁所适应的场景是线程交替执行同步块的情况,如果存在同一时间访问同一锁的情况,就会导致轻量级锁膨胀为重量级锁。

3.3 重量级锁(Mutex Lock)

这种依赖于操作系统 Mutex Lock 所实现的锁我们称之为“重量级锁” Synchronized,是通过对象内部的做监视器锁(monitor)实现。监视器锁是依赖于底层的操作系统的 Mutex Lock来实现,而操作系统实现线程之间的切换这就需要从用 户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,
这就是为什么Synchronized 效率低的原因

3.4 锁升级

随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁(但是锁的升级是单向的, 也就是说只能从低到高升级,不会出现锁的降级)。

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

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

相关文章

ChatGPT对我们的影响-ChatGPT能给我们带来什么

ChatGPT日常应用 ChatGPT是一种应用广泛的自然语言处理算法,其可以应用于多种日常场景。以下是一些ChatGPT的日常应用: 聊天机器人:ChatGPT可用于构建聊天机器人,通过与用户进行自然语言交互来提供个性化的服务和支持。 新闻稿和…

MyBatis零基础入门实践

MyBatis一、MyBatis简介1、MyBatis历史2、MyBatis特性3、MyBatis下载4、和其它持久化层技术对比二、搭建MyBatis1、开发环境2、创建maven工程3、创建MyBatis的核心配置文件4、创建mapper接口5、创建MyBatis的映射文件6、通过junit测试功能7、加入log4j日志功能三、核心配置文件…

代码随想录算法训练营第五十天 | 123. 买卖股票的最佳时机 III、188. 买卖股票的最佳时机 IV

123. 买卖股票的最佳时机 III 关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。 动规五部曲: 1、确定dp数组以及下标的含义 一天一共就有五个状态, 没有股票第一次持有股票第一次不持有股…

SPI协议

SPI协议 物理层 信号线 SCK(Serial Clock):时钟线 MOSI(Master Output, Slave Input ):主设备输出,从设备输入 MISO(Master Input,, Slave Output):主设备输入,从设备输出 SSN(…

API 测试 | 了解 API 接口测试 | API 接口测试指南

什么是 API? API 是一个缩写,它代表了一个 pplication P AGC 软件覆盖整个房间。API 是用于构建软件应用程序的一组例程,协议和工具。API 指定一个软件程序应如何与其他软件程序进行交互。 例行程序:执行特定任务的程序。例程也…

Redux的基本使用详解(从入门到入土)

Redux的基本使用过程详解 学习文档 中文文档: http://www.redux.org.cn/ 英文文档: https://redux.js.org/ Github: https://github.com/reactjs/redux 一,redux是什么 1,介紹: redux是一个专门用于做状态管理的JS库(不是react插件库)。它…

程序员讨厌的“笔试题”,还有存在的必要性吗?

面试,是我们拿到offer的必经之地,在面试中我们会遇到各种“刁难”,而让程序员最为排斥的,非“笔试题”莫属。 △ 截图来源脉脉,如侵删 为什么程序员越来越排斥做面试题呢?我们先来看看网友们的说法&#x…

【Vue2从入门到精通】深入浅出,带你彻底搞懂Vue2组件通信的9种方式

文章目录Vue组件间通信分类1.props / $emit1.1 父组件向子组件传值1.2 子组件向父组件传值2.$parent / $children3.ref / $refs3.1 ref作用于组件3.2 ref作用于Html标签3.3 $nextTick()4.EventBus ($emit / $on)4.1 初始化4.2 发送事件4.3 接收事件4.4 移…

博客首页效果

学习来自风宇blog的博客首页效果 全部用的基本上都是原生的html,css,js特别是flex布局的使用,主轴方向可以是横轴,也可以是纵轴,弹性项还可可以使用百分比sticky粘性布局,作为侧边栏,它不会超出…

分享一个国内可用的免费ChatGPT网站

背景 ChatGPT作为一种基于人工智能技术的自然语言处理工具,近期的热度直接沸腾🌋。 作为一个程序员,我也忍不住做了一个基于ChatGPT的网站,免费!免登陆!!国内可直接对话ChatGPT,也…

c++类和对象

🙆🏼关注作者:玺子写代码 ✍️gitee:玺子写代码 目录👉🏻类的定义👉🏽类的两种定义方式👉🏼类的访问限定符及封装👉🏽访问限定符&…

ML@sklearn@ML流程Part3@AutomaticParameterSearches

文章目录Automatic parameter searchesdemomodel_selection::Hyper-parameter optimizersGridSearchCVegRandomizedSearchCVegNoteRandomForestRegressorMSEpipeline交叉验证🎈egL1L2正则Next stepsUser Guide vs TutorialAutomatic parameter searches Automatic p…

6 计时器(一)

计时器 6.1 TIM TIM简介 TIM(Timer)定时器 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中…

如何在现实场景中随心放置AR虚拟对象?

随着AR的发展和电子设备的普及,人们在生活中使用AR技术的门槛降低,比如对于不方便测量的物体使用AR测量,方便又准确;遇到陌生的路段使用AR导航,清楚又便捷;网购时拿不准的物品使用AR购物,体验更…

Spring-aop面向切面

1、理解必要的专业术语 先看看上面图,这是我的个人理解。(画的丑,主打真实) 1)Advice,通知/增强:类方法中提出来的共性功能(大白话就是提出来的重复代码) 2)Pointcut,切入点/切点&#…

centos7修改ip

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

uniapp国际化配置

1、创建资源文件 创建一个locale文件夹,新增index.js,en.json,zh-hans.json 2.配置locale文件夹中的index.js文件 import Vue from vue import VueI18n from vue-i18n// v8.x import en from ./en.json import zhHans from ./zh-Hans.json import zhHant from .…

Redis大key问题

Redis大key问题 什么是big key? bigKey的危害: 大key不仅仅是占用内存而已,如果是仅仅内存的问题 那么扩大内存就好了。禁止大key是主要是因为你操作redis,比如说读/写等操作redis的时候 会有io操作,大key会导致io操作…

【K8S】k8s中secret使用方法

secret可以加密用户名和密码文件,将其打包成一个secret并在API服务器上创建对象 echo -n admin > ./username.txt echo -n xvagaxx > ./password.txt将username.txt和password.txt打包成secret kubectl create secret generic db-user-pass \--from-file./u…

【Mysql系列】——详细剖析数据库中的存储引擎

【Mysql系列】——详细剖析数据库中的存储引擎😎前言🙌存储引擎什么是存储引擎?Mysql的体系结构:Mysql的体系结构分为四层:连接层服务层引擎层存储层存储引擎的查看存储引擎的指定存储引擎的特点InnoDB介绍InnoDB特点I…