Java面试题——为 什 么 说 Synchronized 是 一 个 悲 观 锁 ?乐 观 锁 的 实 现 原 理又 是 什 么 ? 什 么 是 CAS, 它 有 什 么 特 性 ?

2023-11-14

  • a、Synchronized 显 然 是 一 个 悲 观 锁 , 因 为 它 的 并 发 策 略 是 悲 观 的 :不 管 是 否 会 产 生 竞 争 , 任 何 的 数 据操作 都 必 须 要 加 锁 、 用 户 态 ,核 心 态 转换 、 维 护 锁 计 数 器 和 检 查 是 否 有 被 阻 塞 的 线 程 需 要 被 唤 醒 等 操 作。
  • b、随 着 硬 件 指 令 集 的 发 展 , 我 们 可 以 使 用 基 于 冲 突 检 测 的 乐 观 并 发 策 略 。先 进 行 操 作 , 如 果 没 有 其他线 程 征 用 数 据 , 那 操 作 就 成 功 了 ;如 果 共 享 数 据 有 征 用 , 产 生 了 冲 突 , 那 就 再 进 行 其 他 的 补 偿 措施 。
  • 这 种乐 观 的 并 发 策 略 的 许 多 实 现 不 需 要 线 程 挂 起 , 所 以 被 称 为 非 阻 塞 同 步 。
  • c、乐 观 锁 的 核 心 算 法是 CAS( Compareand Swap, 比 较 并 交 换 ) , 它 涉及 到 三 个 操 作 数 : 内 存 值 、 预 期值 、 新 值 。 当 且 仅 当预 期 值 和 内 存 值 相等 时 才 将 内 存 值 修 改 为 新 值 。这 样 处 理 的 逻 辑 是 , 首 先 检 查 某 块内 存 的 值 是 否 跟之 前 我 读 取 时 的 一样 , 如 不 一 样 则 表 示 期 间 此 内 存 值 已 经 被 别 的 线 程 更 改 过 , 舍 弃 本次 操作 , 否 则说 明 期 间 没 有 其 他 线 程 对 此 内 存 值 操 作 , 可 以 把 新 值 设 置 给 此块 内 存 。
  • d、CAS 具 有 原 子 性 , 它 的 原 子 性由 CPU 硬 件 指 令 实 现 保 证 , 即 使 用JNI 调 用 Native 方 法 调 用 由 C++ 编 写的 硬 件 级 别 指 令 , JDK 中 提供 了Unsafe 类 执 行 这 些 操 作 。

概述

synchronized关键字最主要有以下3种应用方式:

  1. 修饰非静态方法(或者叫实例方法),调用该方法的当前实例充当锁;
  2. 修饰静态方法,类对象充当锁;
  3. 修饰代码块,要指定加锁对象。

1、乐观锁和悲观锁

乐观锁:乐观锁在处理一段代码时,它会乐观的认为读多写少,也就是并发执行的情况概率很低,代码都是串行执行的,他认为每次去拿数据时,别人都不会对数据进行修改,而只有当写数据时才会正式对数据上锁,它会先去获取一下版本号,看一下版本号有没有发生改变,如果发生改变,就会重复读–比较–写的操作(CAS操作),Java中的乐观锁一般都是通过CAS操作实现的。

悲观锁:悲观锁和乐观锁是完全相反的,它会认为读少写多,并发执行的概率很高,它会认为他在读取数据之后还会有线程对数据做出修改,所以他会在读取数据时就会上锁,这样后面的线程就拿不到锁对象了,从而进入阻塞状态,直到获取到锁,这样做会涉及到线程状态的来回切换,代价较高,性能较低,Java中Synchronized就是一个悲观锁。

Synchronized 是一个悲观锁的实现,因为它假设任何时候都有可能发生竞争,因此在执行同步代码块前会先获得锁,并且如果获取不到锁就会一直等待。这样可以确保在同一时间只有一个线程可以访问共享资源,从而保证线程安全。但是这种做法会带来一定的性能损失,因为大部分时间锁并没有被竞争,但是所有线程都需要等待。

相比之下,乐观锁的实现原理是假设竞争很少发生,因此在执行同步代码块前不会先获得锁,而是直接执行操作。在更新共享资源时,先读取资源的版本号,然后进行更新操作。如果其他线程在此期间修改了共享资源,那么版本号就会发生变化,此时更新操作会失败。此时,当前线程可以选择放弃操作,也可以重新尝试更新操作。乐观锁的实现方式通常会比悲观锁更加高效,因为大部分时间不需要等待锁的释放。

CAS(Compare And Swap)是一种基于乐观锁实现的原子操作。它的原理是先比较共享资源的当前值和期望值是否相等,如果相等就使用新值替换当前值。CAS 操作可以保证原子性,因为在执行操作期间,如果共享资源的值发生变化,CAS 操作会失败,此时就会重新尝试操作,直到成功为止。

CAS 操作具有以下特性:

  1. 原子性:CAS 操作是一种原子性操作,可以保证在同一时刻只有一个线程可以修改共享资源。
  2. 无锁操作:CAS 操作不需要加锁,因此不会引起线程阻塞和切换,效率比较高。
  3. ABA 问题:如果共享资源的值在操作过程中从 A 变成了 B,然后再从 B 变成了 A,那么 CAS 操作会错误地认为共享资源的值没有发生变化,从而引发潜在的问题。为了解决这个问题,可以使用版本号等机制来避免。

需要注意的是,CAS 操作虽然能够提高性能,但是也有一定的局限性,比如只能适用于单个共享变量的操作,不能适用于复合操作等场景。在使用 CAS 操作时需要根据实际场景进行取舍。

oldValue与newValue

oldValue:代表之前读到的资源对象的状态值

newValue:代表享要将资源对象的状态值更新后的值
“此时AB线程争抢着去修改资源对象的状态值,然后占用它”
设a抢到了时间片,

a 对比  对象状态值=0, oldValue=0

二者compare,结果相等,符合预期,则swap对象状态值为1

b 对比 对象状态值=1, oldValue=0。

二者compare,结果不等,抢占失败,放弃swap操作。
实际应用中b不放弃swap
实际应用,通常会让b进行自旋(不断第重试cas操作,且配置次数避免死循环)

内置锁synchronized

即synchronized关键字修饰的同步代码块,是一种互斥锁。

每个Java对象都可以用做一个实现同步的锁,这些锁被称为内置锁或监视器锁。

用法1:类方法用synchronized关键字修饰,和synchronized(this)一样,获取的是当前类对象的互斥锁。

class ClassB{
    public synchronized void func1(){}
}

用法2:同步代码块,在任意对象上获取的是该对象的同步锁。

class ClassC{
    public Object lockObj = new Object(); 
    public void func1()
    {
       synchronized(lockObj){
}
    }  
}

参考文章: 

乐观锁(CAS)和悲观锁(synchronized)的详细介绍_傻鱼爱编程的博客-CSDN博客

悲观锁(Synchronized)和乐观锁(CAS)_synchronized是悲观锁吗_wyplj_sir的博客-CSDN博客

何谓悲观锁与乐观锁_林中静月下仙的博客-CSDN博客

常见的锁策略和synchronized实现原理_悲观锁为什么是重量级的_卑微小小羊的博客-CSDN博客

乐观锁与悲观锁讲解,CAS、synchronized、锁升级、ReentrantLock、AQS_synchronized是悲观锁吗_ZZYSY~的博客-CSDN博客 大聪明教你学Java | 深入浅出聊乐观锁与悲观锁(synchronized 悲观锁)_不肯过江东丶的博客-CSDN博客 Java_小弟季义钦的博客-CSDN博客

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

Java面试题——为 什 么 说 Synchronized 是 一 个 悲 观 锁 ?乐 观 锁 的 实 现 原 理又 是 什 么 ? 什 么 是 CAS, 它 有 什 么 特 性 ? 的相关文章

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

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

    我正在尝试在 IntelliJ 中设置 OpenCV 但是我一直在弄清楚如何告诉 IntelliJ 在哪里可以找到本机库位置 在 Eclipse 中 添加 jar 后 您可以在 Build Config 屏幕中设置 Native 库的位置
  • 为什么 JTables 使 TableModel 在呈现时不可序列化?

    所以最近我正在开发一个工具 供我们配置某些应用程序 它不需要是什么真正令人敬畏的东西 只是一个具有一些 SQL 脚本生成功能并创建几个 XML 文件的基本工具 在此期间 我使用自己的 AbstractTableModel 实现创建了一系列
  • 过滤两次 Lambda Java

    我有一个清单如下 1 2 3 4 5 6 7 和 预期结果必须是 1 2 3 4 5 6 7 我知道怎么做才能到7点 我的结果 1 2 3 4 5 6 我也想知道如何输入 7 我添加了i gt i objList size 1到我的过滤器
  • HSQL - 识别打开连接的数量

    我正在使用嵌入式 HSQL 数据库服务器 有什么方法可以识别活动打开连接的数量吗 Yes SELECT COUNT FROM INFORMATION SCHEMA SYSTEM SESSIONS
  • 如何在 Spring 中禁用使用 @Component 注释创建 bean?

    我的项目中有一些用于重构逻辑的通用接口 它看起来大约是这样的 public interface RefactorAwareEntryPoint default boolean doRefactor if EventLogService wa
  • Java 集合的并集或交集

    建立并集或交集的最简单方法是什么Set在 Java 中 我见过这个简单问题的一些奇怪的解决方案 例如手动迭代这两个集合 最简单的单行解决方案是这样的 set1 addAll set2 Union set1 retainAll set2 In
  • 检测并缩短字符串中的所有网址

    假设我有一条字符串消息 您应该将 file zip 上传到http google com extremelylonglink zip http google com extremelylonglink zip not https stack
  • 将 MOXy 设置为 JAXB 提供程序,而在同一包中没有属性文件

    我正在尝试使用 MOXy 作为我的 JAXB 提供程序 以便将内容编组 解组到 XML JSON 中 我创建了 jaxb properties 文件 内容如下 javax xml bind context factory org eclip
  • jdbc mysql loginTimeout 不起作用

    有人可以解释一下为什么下面的程序在 3 秒后超时 因为我将其设置为在 3 秒后超时 12秒 我特意关闭了mysql服务器来测试mysql服务器无法访问的这种场景 import java sql Connection import java
  • Java ResultSet 如何检查是否有结果

    结果集 http java sun com j2se 1 4 2 docs api java sql ResultSet html没有 hasNext 方法 我想检查 resultSet 是否有任何值 这是正确的方法吗 if resultS
  • 如何对不同的参数类型使用相同的java方法?

    我的问题 我有 2 个已定义的记录 创建对象请求 更新对象请求 必须通过实用方法进行验证 由于这两个对象具有相同的字段 因此可以对这两种类型应用相同的验证方法 现在我只是使用两种方法进行重载 但它很冗长 public record Crea
  • 在我的 Spring Boot 示例中无法打开版本 3 中的 Swagger UI

    我在 Spring Boot 示例中打开 swagger ui 时遇到问题 当我访问 localhost 8080 swagger ui 或 localhost 8080 root api name swagger ui 时出现这种错误 S
  • java for windows 中的文件图标叠加

    我正在尝试像 Tortoise SVN 或 Dropbox 一样在文件和文件夹上实现图标叠加 我在网上查了很多资料 但没有找到Java的解决方案 Can anyone help me with this 很抱歉确认您的担忧 但这无法在 Ja
  • 使用 AsyncTask 传递值

    我一直在努力解决这个问题 但我已经到了不知道该怎么办的地步 我想做的是使用一个类下载文件并将其解析为字符串 然后将该字符串发送到另一个类来解析 JSON 内容 所有部件都可以单独工作 并且我已经单独测试了所有部件 我只是不知道如何将值发送到
  • Cucumber 0.4.3 (cuke4duke) 与 java + maven gem 问题

    我最近开始为 Cucumber 安装一个示例项目 并尝试使用 maven java 运行它 我遵循了这个指南 http www goodercode com wp using cucumber tests with maven and ja
  • CamcorderProfile.videoCodec 返回错误值

    根据docs https developer android com reference android media CamcorderProfile html 您可以使用CamcorderProfile获取设备默认视频编解码格式 然后将其
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • Spring Boot 无法更新 azure cosmos db(MongoDb) 上的分片集合

    我的数据库中存在一个集合 documentDev 其分片键为 dNumber 样本文件 id 12831221wadaee23 dNumber 115 processed false 如果我尝试使用以下命令通过任何查询工具更新此文档 db
  • Spring Rest 和 Jsonp

    我正在尝试让我的 Spring Rest 控制器返回jsonp但我没有快乐 如果我想返回 json 但我有返回的要求 完全相同的代码可以正常工作jsonp我添加了一个转换器 我在网上找到了用于执行 jsonp 转换的源代码 我正在使用 Sp

随机推荐

  • 位运算符规则

    位运算符规则 左移运算符 lt lt 右移运算符 gt gt 无符号右移运算符 gt gt gt 左移运算符 lt lt 运算规则 丢弃左边 高位 指定位数 右边 低位 补0 右移运算符 gt gt 运算规则 丢弃右边 低位 指定位数 左边
  • 软件测试的职业发展和规划(一)

    作为很多软件测试岗位的朋友来说 职业发展和规划一直是一个比较模糊的概念 知道其重要 却不知如何规划更符合自己的实际情况 下面 我们就分三种情况来简单说一说 一 高管理 低技能 即是我们通常所说的管理路线 在IT业 这个方向的成功者不乏项目经
  • 使用react-pdf预览pdf

    在使用umi构建的react项目中如何实现预览pdf 如果PDF中包含印章该如何使印章展示出来 1 安装依赖 yarn add react pdf react pdf https github com wojtekmaj react pdf
  • Mapped Statements collection does not contain value for

    Caused by java lang IllegalArgumentException Mapped Statements collection does not contain value for com wt mss dao daoi
  • React+Ant.Design 从零开始搭建个人博客实战教程01 —— 起步

    简介 刚入手一个服务器 打算搭个个站 平时工作都是用vue 为了扩展自己的实战能力 来从头开始实战用用react吧 结合ant design一起开发 然后后台nodejs来写 编写我的第一个教程文章 从头到尾记录整个过程 因为是实战项目 部
  • ad中封装绿色解决办法

    1是在工具 检查规则中 把一些项取消检查
  • 推荐一个将MD格式的文档轻松转换到微信公众号的工具

    因为微信公众号自带的编辑器不是特别友好 这也是一个痛点 之前也有使用过google插件 但不是特别灵活 现在推荐的这款工具可以很好的支持将MD格式的文档直接进行渲染 还是非常好用的 话不多说 先给出工具地址 https md openwri
  • 花生壳 Linux arm

    安装和使用Linux花生壳服务 一 安装说明 以CentOS 5为例 1 安装必要的开发包 root localhost yum install gcc gcc c autoconf automake 2 下载phddns 2 0 2 16
  • MongoDB图形化工具下载和使用

    文章目录 MongoDB图形化工具 1 下载地址 2 打开MongoDB服务 3 Compass界面 3 1 连接Mongo 3 2 创建数据库 3 3 创建集合 3 4 删除集合 3 5 增 3 6 改 3 7 删 3 8 查 3 9 导
  • TRPO算法详解

    答主最近学到TRPO 这算法确实很难理解 现在记录答主现在的一点想法 留存记录 先放参考文献 方便大家学习 Reference 1 Sutton R S Barto A G Reinforcement learning An introdu
  • 数组指针数组的定义及使用(about array of pointer of array)

    数组指针数组 array pointer array 该怎么定义和使用呢 如下 定义 define MsgCnt 3 define MsgLen 8 typedef char MsgArray MsgCnt MsgLen typedef c
  • J2EE之XML建模

    目录 一 什么叫XML建模 二 XML建模 1 根据XML配置文件元素节点创建元素节点实体类 2 利用dom4j xpath技术实现XML建模 一 什么叫XML建模 将XML配置文件中的元素 属性 文本信息转换成对象的过程叫做XML建模 二
  • 实验四,静态成员与友元

    一 实验目的和要求 了解成员函数的特性 掌握静态成员 友元等概念 二 实验内容 1 调试下列程序 写出输出结果 并分析输出结果 sy4 1 cpp include
  • python 大乐透号码生成器

    选号规则 前区1 35的范围随机产生不重复的5个号码 后区在1 12范围内随机生成2个不重复的2个号码 如下 from random import sample def number front sample str i for i in
  • 一、PWM 输出控制电机

    PWM 输出控制电机 电机系列 一 PWM 输出控制电机 1 相关 IO 介绍 2 编写 PWM 输出库函数 PWM h PWM c 3 控制函数 control h control c 4 main函数 电机系列 一 PWM 输出控制电机
  • 关闭jvm的方式

    1 System exit status 不管status为何值都会退出程序 System exit 0 是正常退出程序 而System exit 1 或者说非0表示非正常退出程序 2 System exit 0 和dispose Syst
  • MySQL踩坑笔记(1)

    mysql gt set password for 用户名 localhost password 新密码 这个是错的 mysql gt alter user 用户名 登录主机 identified by 密码 自定义 这个是对的 mysql
  • Linux全网超详细RHLinux安装PHP8.2.9 (2023年8月最新版)

    目录 进入PHP官方网站 1 下载安装包 2 解压安装包文件 3 安装php文件 安装提示sqlite3 4 安装过程中出现错误修复 5 查看一下php版本 6 启动php服务 进入PHP官方网站 PHP网址 https www php n
  • keras卷积神经网络入门-笑脸检测

    keras卷积神经网络入门 笑脸检测 Keras简介 1 库函数导入 2 查看数据集 3 构建模型 4 训练模型 5 预测自己的图片 Keras简介 Keras以其强大的封装结构 让我们不必过多的考虑神经网络间的计算 极大简化了tensor
  • Java面试题——为 什 么 说 Synchronized 是 一 个 悲 观 锁 ?乐 观 锁 的 实 现 原 理又 是 什 么 ? 什 么 是 CAS, 它 有 什 么 特 性 ?

    a Synchronized 显 然 是 一 个 悲 观 锁 因 为 它 的 并 发 策 略 是 悲 观 的 不 管 是 否 会 产 生 竞 争 任 何 的 数 据操作 都 必 须 要 加 锁 用 户 态 核 心 态 转换 维 护 锁 计