多线程的锁

2023-10-31

简介

1、失败后进行锁膨胀:偏向锁 --> 轻量锁 --> 重量锁。

2、偏向锁:认为没有竞争,每次都是同一个线程获取的锁,所以第一次通过CAS后,把线程id放到锁对象Mark Word后,以后每次都不需要CAS操作

3、轻量级锁:认为没有竞争,每次都是不同线程轮流获取的锁,所以利用CAS拷贝Mark Word副本对象到线程的栈中存储,以后每次通过CAS操作减少使用互斥量的开销。

自旋锁

多线程同步时,频繁挂起和恢复线程开销比较大,让线程执行一个忙循环(自旋),就是所谓的自旋锁。jdk1.6后引入了自适应自旋锁,自旋时间由前一次在同一个锁上的自旋时间和锁的拥有者的状态来决定。

锁消除

虚拟机及时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除。如:字符串通过“+”进行连接的时候,会转换为Stringbuilder,Stringbuilder中的锁可能会被消除。

锁粗化

锁粒度尽可能小,如果Stringbuilder的append()中的锁比较频繁,可能会在整个方法加一次锁。

轻量级锁

1、概述:提升程序同步性能的依据是“对于绝大部分的锁,在整个同步周期内都是不存在竞争的”这一经验法则。如果没有竞争,不同线程可轮流通过轻量级锁,CAS操作成功避免了使用互斥量的开销;但如果确 实存在锁竞争,除了互斥量的本身开销外,还额外发生了CAS操作的开销。因此在有竞争的情况下, 轻量级锁反而会比传统的重量级锁更慢。

2、对象头分为两部分信息,1、用于存储对象自身运行时的数据,如哈希码、GC分代年龄等这部分数据长度在32位和64位虚拟机中分别为32bit和64bit,称作mark word.

3、虚拟机先将在当前线程的栈帧中建立名为锁记录(lock record)的空间,用于存储锁对象目前的mark word的拷贝(displaced mark word),然后虚拟机将cas操作尝试将对象的mark word更新为指向lock record的指针,更新成功,那么这个线程拥有了该对象的锁,对象处于轻量级锁状态。更新失败,会检查对象mark word是否指向当前线程的栈帧,则直接进入同步代码块继续执行。否则说明锁已经被其它线程抢占。如果存在多个线程同时竞争一把锁,轻量锁就会膨胀为重量锁

在这里插入图片描述

解锁

轻量锁的解锁过程也是利用 CAS 来实现的,会尝试锁记录替换回锁对象的 Mark Word 。如果替换成功则说明整个同步操作完成,失败则说明有其他线程尝试获取锁,这时就会唤醒被挂起的线程(此时已经膨胀为重量锁)

轻量锁能提升性能的原因是:认为大多数锁在整个同步周期都不存在竞争,所以使用 CAS 比使用互斥开销更少。但如果锁竞争激烈,轻量锁就不但有互斥的开销,还有 CAS 的开销,甚至比重量锁更慢。

偏向锁

如果轻量级锁是无竞争情况下使用CAS操作去消除同步使用的互斥量,那偏向锁就是在无竞争环境下把整个同步都消除掉。

偏向锁的特征是:认为锁不存在多线程竞争,并且应由同一个线程多次获得锁。

当线程访问同步块时,会使用 CAS 将线程 ID 更新到锁对象的 Mark Word 中,如果更新成功则获得偏向锁,并且之后每次进入这个对象锁相关的同步块时都不需要再次获取锁了。

在这里插入图片描述

释放锁

当有另外一个线程获取这个锁时,持有偏向锁的线程就会释放锁,释放时会等待全局安全点(这一时刻没有字节码运行),接着会暂停拥有偏向锁的线程,根据锁对象目前是否被锁来判定将对象头中的 Mark Word 设置为无锁或者是轻量锁状态。

轻量锁可以提高带有同步却没有竞争的程序性能,但如果程序中大多数锁都存在竞争时,那偏向锁就起不到太大作用。可以使用 -XX:-userBiasedLocking=false 来关闭偏向锁,并默认进入轻量锁。

乐观锁

对并发操作产生的线程问题持乐观态度,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。

悲观锁

不管三七二十一,直接上独占锁,就像synchronized

分段锁

把一个锁分解为多个锁

分解锁

锁上存在适中而不是很激烈的竞争时,将一个锁分解为两个锁

读写锁

ReentrantReadWriteLock:使用场景是读多写少时。

1、可重入

2、默认是非公平的锁

3、线程持有写锁不能在不释放写锁的情况下获得读锁,反之可以。

4、如果锁由读线程持有,另一个线程请求写锁,那么其他读线程都不能获得读取锁,直到写线程释放写入锁。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多线程的锁 的相关文章

  • Java中有没有一种方法可以通过名称实例化一个类?

    我正在寻找问题 从字符串名称实例化一个类 https stackoverflow com questions 9854900 instantiate an class from its string name它描述了如何在有名称的情况下实例
  • 如何将本机库链接到 IntelliJ 中的 jar?

    我正在尝试在 IntelliJ 中设置 OpenCV 但是我一直在弄清楚如何告诉 IntelliJ 在哪里可以找到本机库位置 在 Eclipse 中 添加 jar 后 您可以在 Build Config 屏幕中设置 Native 库的位置
  • 在 Java 中克隆对象 [3 个问题]

    这样做会调用Asub的clone方法吗 或者Asub深度克隆是否正确 如果没有的话 有没有办法通过这种方法对Asub进行深度克隆呢 abstract class Top extends TopMost protected Object cl
  • 日期语句之间的 JPQL SELECT [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我想将此 SQL 语句转换为等效的 JPQL SELECT FROM events WHERE events date BETWE
  • 如何使用assertEquals 和 Epsilon 在 JUnit 中断言两个双精度数?

    不推荐使用双打的assertEquals 我发现应该使用带有Epsilon的形式 这是因为双打不可能100 严格 但无论如何我需要比较两个双打 预期结果和实际结果 但我不知道该怎么做 目前我的测试如下 Test public void te
  • 谷歌应用程序引擎会话

    什么是java应用程序引擎 默认会话超时 如果我们将会话超时设置为非常非常长的时间 会不会产生不良影响 因为谷歌应用程序引擎会话默认情况下仅存储在数据存储中 就像facebook一样 每次访问该页面时 会话仍然永远存在 默认会话超时设置为
  • 在接口中使用默认方法是否违反接口隔离原则?

    我正在学习 SOLID 原则 ISP 指出 客户端不应被迫依赖于他们所使用的接口 不使用 在接口中使用默认方法是否违反了这个原则 我见过类似的问题 但我在这里发布了一个示例 以便更清楚地了解我的示例是否违反了 ISP 假设我有这个例子 pu
  • 来自 dll 的 Java 调用函数

    我有这个 python 脚本导入zkemkeeperdll 并连接到考勤设备 ZKTeco 这是我正在使用的脚本 from win32com client import Dispatch zk Dispatch zkemkeeper ZKE
  • 从最终实体获取根证书和中间证书

    作为密码学的菜鸟 我每天都会偶然发现一些简单的事情 今天只是那些日子之一 我想用 bouncy castle 库验证 java 中的 smime 消息 我想我几乎已经弄清楚了 但此时的问题是 PKIXparameters 对象的构建 假设我
  • java.lang.IllegalStateException:提交响应后无法调用 sendRedirect()

    这两天我一直在尝试找出问题所在 我在这里读到我应该在代码中添加一个返回 我做到了 但我仍然得到 java lang IllegalStateException Cannot call sendRedirect after the respo
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • 如何对不同的参数类型使用相同的java方法?

    我的问题 我有 2 个已定义的记录 创建对象请求 更新对象请求 必须通过实用方法进行验证 由于这两个对象具有相同的字段 因此可以对这两种类型应用相同的验证方法 现在我只是使用两种方法进行重载 但它很冗长 public record Crea
  • 如何访问JAR文件中的Maven资源? [复制]

    这个问题在这里已经有答案了 我有一个使用 Maven 构建的 Java 应用程序 我有一个资源文件夹com pkg resources 我需要从中访问文件 例如directory txt 我一直在查看各种教程和其他答案 但似乎没有一个对我有
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • 获取文件的总大小(以字节为单位)[重复]

    这个问题在这里已经有答案了 可能的重复 java 高效获取文件大小 https stackoverflow com questions 116574 java get file size efficiently 我有一个名为 filenam
  • java for windows 中的文件图标叠加

    我正在尝试像 Tortoise SVN 或 Dropbox 一样在文件和文件夹上实现图标叠加 我在网上查了很多资料 但没有找到Java的解决方案 Can anyone help me with this 很抱歉确认您的担忧 但这无法在 Ja
  • 关键字“table”附近的语法不正确,无法提取结果集

    我使用 SQL Server 创建了一个项目 其中包含以下文件 UserDAO java public class UserDAO private static SessionFactory sessionFactory static se
  • 专门针对 JSP 的测试驱动开发

    在理解 TDD 到底是什么之前 我就已经开始编写测试驱动的代码了 在没有实现的情况下调用函数和类可以帮助我以更快 更有效的方式理解和构建我的应用程序 所以我非常习惯编写代码 gt 编译它 gt 看到它失败 gt 通过构建其实现来修复它的过程
  • 如何使用mockito模拟构建器

    我有一个建造者 class Builder private String name private String address public Builder setName String name this name name retur
  • Java中super关键字的范围和使用

    为什么无法使用 super 关键字访问父类变量 使用以下代码 输出为 feline cougar c c class Feline public String type f public Feline System out print fe

随机推荐

  • 计算机算法常用术语中英对照(分为两部分 其中一部分表格形式 )

    第一部分 Data Structures 基本数据结构 Dictionaries 字典 Priority Queues 堆 Graph Data Structures 图 Set Data Structures 集合 Kd Trees 线段
  • Python实现子线程代码“同时”执行完毕后,再执行后续函数模块

    在python中用多线程完成任务时 在后面添加了一个提醒函数 结果发现线程开启后提醒函数就触发了 解决方法 将多线程join 起来 就会跑完所有多线程任务再执行后续的函数模块 join 的使用方法 import threading impo
  • pgsql:获取分组中最大或最小的一条数据

    步骤1 查询并排序各分组的记录 sql的查询语句如下 SELECT tb curr read tb arch id ROW NUMBER OVER PARTITION by arch id ORDER BY year month desc
  • AWS实例3T磁盘初始化分区及docker环境部署

    文章目录 一 背景说明 二 磁盘分区 2 1 安装分区工具 2 2 查看是否存在数据盘 2 3 使用Parted工具为数据盘进行分区 2 4 系统重读分区表 2 5 为 dev vdb1分区创建文件系统 2 6 挂载磁盘 三 安装docke
  • Qt进行CSV文件操作

    Qt操作csv文件 csv文件简述 逗号分隔值 Comma Separated Values CSV 有时也称为字符分隔值 因为分隔字符也可以不是逗号 其文件以纯文本形式存储表格数据 数字和文本 纯文本意味着该文件是一个字符序列 不含必须像
  • X86指令:NOP指令

    NOP指令的作用 通常NOP用于对齐指令的地址 NOP指令的特性 因为NOP是X86指令中最短的 只有1byte 处理器执行NOP指令时 不进行任何的操作 不会影响系统的状态 NOP也有其他的用途 1 编程时如果使用了支持lable标记的编
  • javascript函数相关例题

    前言 虽然for也能实现一些简单的 重复操作 但是 比较具有局限性 我们js 里面 也有非常多的相同代码 可能需要大量重复使用 此时我们可以利用函数 一 函数是什么 函数 就是 封装了 一段 可被重复调用执行的 代码块 可以实现大量代码的重
  • 删除git在windows上的凭证

    由于本人安装git的客户端以及开始下载github上的项目代码 第一次输入的账户名以及密码错误 需要删除windows上自己保存的账号密码凭证 我自己的电脑配置 运用命令行打开控制面板也十分方便 快捷键 Win R 打开运行窗口 输入 co
  • vs2010 使用QT

    首先不要使用中文目录 1 下载Qt的安装包和VS2010的Qt插件 2 安装Qt SDK 3 安装Qt的VS开发插件 4 编译Qt Qt默认使用mingw进行编译 如果要使用VS2010开发 需要将Qt重新编译 进入开始菜单Microsof
  • 在VS8里面 fatal error C1083: 无法打开包括文件:“iostream.h”: No such file or directory

    fatal error C1083 无法打开包括文件
  • pointCloudLibrary点云库使用

    pointCloudLibrary点云库使用 准备 下载源码 https github com PointCloudLibrary pcl 这个是pointCloudLibrary 但不包括 Boost Eigen FLANN OpenNI
  • gdb调试子进程

    GDB 是 linux 系统上常用的调试工具 本文介绍了使用 GDB 调试多进程程序的几种方法 并对各种方法进行比较 GDB 是 linux 系统上常用的 c c 调试工具 功能十分强大 对于较为复杂的系统 比如多进程系统 如何使用 GDB
  • 「前端学习」vue入门-井字棋

    1 Vue 学习路线 2 使用 vue cli 创建 vue 项目 注意 vue cli 对应版本 2 1 创建项目 在当前目录下创建项目 vue create 注意 项目文件名不能由大写 2 2 配置 3 Vue 组件 不成问的规定 默认
  • CentOS 安装 Docker 和 DockerCompose,超详细

    0 安装Docker Docker 分为 CE 和 EE 两大版本 CE 即社区版 免费 支持周期 7 个月 EE 即企业版 强调安全 付费使用 支持周期 24 个月 Docker CE 分为 stable test 和 nightly 三
  • [885]Tensorflow设置CUDA_VISIBLE_DEVICES来控制GPU的使用

    os environ CUDA DEVICE ORDER PCI BUS ID 按照PCI BUS ID顺序从0开始排列GPU设备 os environ CUDA VISIBLE DEVICES 0 设置当前使用的GPU设备仅为0号设备 设
  • Java:关于Java中的线程中断的几种方法

    Java 关于Java中的线程中断的几种方法 1 使用线程的stop 来中断线程 2 使用线程的interrupt 来中断线程 3 通过共享变量来控制 使用线程的stop 来中断线程 这种方式是直接调用线程的stop 方法 可以直接让线程终
  • 子网地址,广播地址,子网掩码,主机地址范围,求法总结

    熟练转换 十进制 gt 二进制 如给出 主机数或者说划分多少个子网 这时候 我们用2的n次方 2 gt 主机数或子网数 求出n n表示子网位数 那么子网总数为 2的n次方 而一个字节8位 那么剩下8 n 位主机号 可得出 子网间隔为2的 8
  • NTP-时间同步,(Linux / Windows)服务端搭建到时间同步配置操作-直接拿下

    一 NTP服务器搭建跟同步配置 centos8 1 安装chrony服务 centos8系统版本自带 centos8以前的版本为ntpd服务 yum install chrony 2 启动服务 Systemctl start chronyd
  • MySQL——变量与游标

    今天我们来一起学习MySQL中 的变量 系统变量与用户变量 以及什么是游标 游标如何使用 1 变量 在 MySQL 数据库的存储过程和函数中 可以使用变量来存储查询或计算的中间结果数据 或者输出最终的结果数据 在 MySQL 数据库中 变量
  • 多线程的锁

    简介 1 失败后进行锁膨胀 偏向锁 gt 轻量锁 gt 重量锁 2 偏向锁 认为没有竞争 每次都是同一个线程获取的锁 所以第一次通过CAS后 把线程id放到锁对象Mark Word后 以后每次都不需要CAS操作 3 轻量级锁 认为没有竞争