【多线程与高并发(锁)】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 锁升级

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

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

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

相关文章

Obsidian:实现日记记录【设计并使用模板】

问题背景 我是一个比较喜欢记录的人,有一定的写日记的习惯的,但是我又不太喜欢将自己的个人的数据寄人篱下,放在别人的数据库中。 于是就想着将自己的日记存放在自己本地的磁盘中…… 在一次偶然在B站中翻找资料时,我发现了这个…

Linux-Shell设计

一、shell 总论 ​ shell 就是“壳程序”,这个名字是针对 kernel 来说的,也就是在操作系统外围的程序(严格的讲,已经不是操作系统了)。宏观上的 shell 是所有的应用程序,而狭义上的 shell,指的…

STM32CubeMXA安装和创建项目

STM32CubeMXA安装和创建项目 安装STM32CubeMXA STM32CubeMX 运行环境搭建包含两个部分。首先是 Java 运行环境安装,其次是 STM32CubeMX 软件安装。 安装 JAVA 环境 对于 Java 运行环境,大家可以到 Java 官网 www.java.com 下载最新的 Java 软件 安装…

CSS 扫盲

✏️作者:银河罐头 📋系列专栏:JavaEE 🌲“种一棵树最好的时间是十年前,其次是现在” 目录引入方式内部样式内联样式外部样式CSS 选择器CSS 常用属性值字体属性设置字体大小粗细文字样式文本属性文本颜色文本对齐文本装…

使用Jmeter进行http接口测试

前言: 本文主要针对http接口进行测试,使用Jmeter工具实现。 Jmter工具设计之初是用于做性能测试的,它在实现对各种接口的调用方面已经做的比较成熟,因此,本次直接使用Jmeter工具来完成对Http接口的测试。 一、开发接口…

【Unity项目实战】从零手戳一个背包系统

首先我们下载我们的人物和背景资源,因为主要是背包系统,所以人物的移动和场景的搭建这里我们就不多讲了,我这里直接提供基础项目源码给大家去使用就行 基础项目下载地址: 链接: https://pan.baidu.com/s/1o7_RW_QQ1rrAbDzT69ApRw 提取码: 8s95 顺带说一下,这里用到了uni…

uniCloud开发api接口服务

首先创建一个云对象: 在创建的云对象的index.Obj.js中进行编码: const db uniCloud.database() module.exports {_before: function () { // 通用预处理器},async get(){//demo-user 是云数据中的一个表名let res await db.collection("demo-us…

最易学和最难学编程语言排行榜!

如果问一个程序员最容易学习的语言,就像问一个人他们最喜欢的冰淇淋。每个人都有自己的偏好,永远没有真正的正确答案。 正如开发者和教育家 Marek Zaluski 曾经说的那样,"编程语言是由程序员创造的,为程序员服务"。这几…

Hashtable是什么?它和Hashmap有什么区别?

博主简介:努力的打工人一枚博主主页:xyk:所属专栏: JavaEE初阶目录 一、什么是Hashtable? 二、Hashtable特点 2.1 Hashtable是怎么加锁的? 2.2Hashtable为什么不允许键值为null? 2.3Hashtable为什么线程安全&…

电动汽车热管理方案

热管理技术作为汽车节能、提高经济性和保障安全性的重要措施,在汽车研发过程中具有重要作用。传统燃油汽车的热管理系统主要包括发动机、变速器散热系统和汽车空调,而电动汽车的热管理系统在燃油汽车热管理架构的基础之上,又增加了电机电控热…

Docker实现MySQL8主从读写分离【超简洁】

1、首先拉取镜像 docker pull mysql 2、创建主库容器 docker run -p 3388:3306 --name master -e MYSQL_ROOT_PASSWORD123456 -d mysql --server-id1 --log-binbin-log --binlog-do-dbznzm-dlaq 说明: docker run 表示创建并运行容器-p 3388:3306 把宿主机的…

【SQL开发实战技巧】系列(四十):Oracle12C常用新特性☞可以在同样的列(列组合)上创建多个索引以及可以对DDL操作进行日志记录

系列文章目录 【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事 【SQL开发实战技巧】系列(二):简单单表查询 【SQL开发实战技巧】系列(三):SQL排序的那些事 【SQL开发实战技巧…

软件测试岗,4 轮面试成功拿下字节 Offer..........

一共经历了四轮面试:技术4面+HR面。 特整理出所涉及的全部知识点,并复盘了完整面试题及答案,分享给大家,希望能够帮到一些计划面试字节的朋友。 一、测试基础理论类 怎么编写案例?软件测试的两种方法测试结束的标准…

python好玩的短代码

Python语言是一种流行的编程语言,在 Python语言中有很多有趣的特性,比如: 1.变量可以定义为字符串,也可以定义为字符串对象 2.变量可以用来初始化一个函数或模块,函数或者模块可以定义成一个类,这个类被称为…

不负期待,载誉收官 | 迅镭激光2023ITES深圳展圆满落幕!

4月1日,历时4天的2023 ITES深圳工业展在深圳国际会展中心圆满收官!本届展会聚焦“金属切削机床、金属成形机床、核心工业技术、机器人及自动化设备、智能物流、工业零件”六大产业集群,云集1295家参展企业,品牌阵容高端先进、丰富多元&#x…

轻轻松松编译 Jmeter 源码,再也不求人

Jmeter工具,大家在做接口测试、自动化测试,都是经常会用到的,甚至在做性能测试时,是首选工具。Jmeter本身是用java语言编写的开源的工具,在jmeter.apache.org官网上,可以下载。 但是,也耐不住那…

Leetcode.130 被围绕的区域

题目链接 Leetcode.130 被围绕的区域 mid 题目描述 给你一个 m x n的矩阵 board,由若干字符 X和 O,找到所有被 X围绕的区域,并将这些区域里所有的 O用 X填充。 示例 1: 输入:board [[“X”,“X”,“X”,“X”],[“X…

继承(C++)

继承继承的概念及定义继承的概念继承的定义定义格式继承关系和访问限定符继承基类成员访问方式的变化基类和派生类对象赋值转换继承中的作用域派生类的默认成员函数继承与友元继承与静态成员复杂的菱形继承及菱形虚拟继承虚拟继承的原理继承的概念及定义 继承的概念 继承是面…

Spring-aop面向切面

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

Tomcat使用https配置实战

一、tomcat证书配置 首先,要实现https,就必须先具有tomcat证书。我们在安装tomcat的时候,肯定都先安装了JAVA,而JAVA中有自带的证书生成工具keytool,今天,我们就使用keytool来生成tomcat的证书。 执行命令…
最新文章