java锁策略和synchronized锁机制

2023-05-16

一、常见的锁策略

1.乐观锁 vs 悲观锁

锁的实现者,预测接下来的锁冲突概率大不大,根据这个概率决定接下来该做什么。

乐观锁:预测冲突不大,做的工作少一些,效率更高一些

悲观锁:预测冲突大,做的工作更多,效率低一些

举个生活中的例子:

在全国放开的时候,A认为既然都放开了,就不会存在再一次封地区,所以就没有任何准备;B认为疫情反复无常,有可能还会封地区,所以B依旧囤了很多药品和食物在家里面。

A就属于乐观锁,什么都没有准备。B就属于悲观锁,做了很多的准备工作。

2.轻量级锁 vs 重量级锁

轻量级锁:加锁解锁,过程更快更高效

​ 1.少量的内核态用户态切换.

​ 2.不太容易引发线程调度

重量级锁:加锁解锁,过程慢,低效

​ 1.大量的内核态用户态切换

​ 2.很容易引发线程的调度

内核态、用户态

image-20230326213041267

假设在银行办理业务,需要你打印一份资料

1.你让工作人员帮你打印,虽然最后会帮你打印,但是你不能保证他中途没有其他的事情,而是直接给你打印资料。应用程序,在同一时刻要服务很多的程序。

2.你自己打印资料,你直接就能把资料打印了。

纯用户态操作,时间是可控的

涉及到了内核态,时间就不能控制

3.自旋锁 vs 挂起等待锁

自选锁:在获取锁失败后,即再次尝试获取锁, 无限循环, 直到获取到锁为止,一旦锁被其他线程释放, 就能第一时间获取到锁。是一种轻量级锁。

挂起等待锁:在获取锁失败后,会堵塞等待(放弃CPU,进入等待队列), 然后等到锁被释放的时候再有操作系统调度。是一种重量级锁。

例子:

在追求一个女神的时候,当男生向女神表白后, 女神说: 你是个好人, 但是我有男朋友了~~

挂起等待锁: 陷入沉沦不能自拔… 过了很久很久之后, 突然女神发来消息, “咱俩要不试试?” (注意,

这个很长的时间间隔里, 女神可能已经换了好几个男票了)。

自旋锁: 死皮赖脸坚韧不拔. 仍然每天持续的和女神说早安晚安. 一旦女神和上一任分手, 那么就能

立刻抓住机会上位。

自旋锁

优点: 没有放弃 CPU, 不涉及线程阻塞和调度, 一旦锁被释放, 就能第一时间获取到锁。

缺点: 如果锁被其他线程持有的时间比较久, 那么就会持续的消耗 CPU 资源. (而挂起等待的时候是

不消耗 CPU 的)。

4.互斥锁 vs 读写锁

互斥锁:进入synchroniced属于加锁,出synchroniced属于释放锁,两者不能同时发生。

读写锁:多线程之间,数据的读取方之间不会产生线程安全问题,但数据的写入方互相之间以及和读者之间都需要进行互斥。如果两种场景下都用同一个锁,就会产生极大的性能损耗

两个线程都只是读一个数据, 此时并没有线程安全问题. 直接并发的读取即可.

两个线程都要写一个数据, 有线程安全问题.

一个线程读另外一个线程写, 也有线程安全问题.

  • 读锁和读锁:不会锁竞争,不会阻塞等待
  • 写锁和写锁:有锁竞争
  • 读锁和写锁:有锁竞争

5.可重入锁 vs 不可重入锁

  • 可重入锁: 一个线程针对同一把锁连续加锁两次,不会出现死锁
  • 不可重入锁: 一个线程针对同一把锁连续加锁两次,会出现死锁

image-20230326220618060

这种属于不可重入锁

在java中, 并不容易出现死锁,synchroniced是可重入锁,加锁的时候会判断当前尝试加锁的线程是不是锁的拥有者,是就直接放行。

6.公平锁 vs 非公平锁

  • 公平锁: 多个线程在等待一把锁的时候, 遵循先来后到原则, 谁是先来的, 谁就先获得这把锁.
  • 非公平锁: 多个线程等待同一把锁, 不遵守先来后到原则, 每个人等待线程获取锁的概率是均等的.

image-20230326220939143

公平锁

image-20230326221015503

非公平锁

image-20230326221050997

二、synchronized锁机制

1.synchronized的特点

  • 既是乐观锁,也是悲观锁
  • 既是轻量锁,也是重量级锁
  • 轻量级锁基于自旋锁实现,重量级锁基于挂起等待锁实现
  • 不是读写锁
  • 是可重入锁
  • 是非公平锁

2.锁升级

image-20230326222044844

  • 最开始加锁的时候是偏向锁状态,只是让线程针对锁有个标记,如果整个代码执行过程没有其他的线程参与这个锁竞争,那么从始至终都是偏向锁,如果有线程来尝试竞争这个锁,偏向锁就会升级成真正的锁(自旋锁),这个时候其他的线程就只能阻塞等待。

  • 自旋锁虽然执行速度很快,但是消耗大量的cpu,如果大量的线程参与锁竞争,为了较少cpu的消耗,就会升级成重量级锁。

偏向锁

只是做一个标记,没有其他线程来竞争锁,就永远不会升级

非必要,不加锁

3.锁消除

在编译阶段,检测当前代码是否是多线程执行、是否有必要加锁,如果没有必要,但是又有锁的存在,就会在编译过程中自动把锁去掉。

有些应用程序的代码中, 用到了 synchronized, 但其实没有在多线程环境下. (例如 StringBuffer)

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");

此时每个 append 的调用都会涉及加锁和解锁. 但如果只是在单线程中执行这个代码, 那么这些加锁解锁操作是没有必要的, 白白浪费资源开销.

4.锁粗化

如果程序会频繁的加锁、解锁,编译器就可能把操作优化成一个粒度更粗的锁。

image-20230327085929295

每次加锁解锁,都是有开销的,为了程序运行更加的高效,就引入了锁粗化

image-20230327090803657

image-20230327091431756

通过一次电话把所有事情汇报完毕明显比三次电话分别汇报的效率高了不少

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

java锁策略和synchronized锁机制 的相关文章

  • 如何使用Spring WebClient进行同步调用?

    Spring Framework in 休息模板 https docs spring io spring framework docs current javadoc api org springframework web client R
  • NoInitialContextException:heroku 战争部署

    我一直在开发一个 J2EE 项目 并且在其中使用连接池 也通过部署在 heroku 上的数据库进行访问 我使用以下代码来设置 Connection 对象 Context initContext new InitialContext Cont
  • Java 7 默认语言环境

    我刚刚安装了 jre7 我很惊讶地发现我的默认区域设置现在是 en US 对于jre6 它是de CH 与jre7有什么不同 默认区域设置不再是操作系统之一吗 顺便说一句 我使用的是Windows7 谢谢你的回答 编辑 我已经看到了语言环境
  • (Java) App Engine 中的静态文件无法访问

    The 示例文档 http code google com appengine docs java gettingstarted staticfiles html表示您只需将文件放在 war 或子目录 中 并且应该可以从主机访问它们 只要它
  • 将SQL数据引入jquery availabletag

    我正在尝试制作自动完成文本框 但如何将 SQL 数据包含到 jquery 可用标记并循环它 我无法根据以下代码执行该功能 任何帮助 将不胜感激 谢谢 这是我的预期输出 预期结果演示 http jsfiddle net VvETA 71 jq
  • 如何在java Spring Boot中实现通用服务类?

    我有许多具有重复代码的服务 我想知道如何实现通用服务 以便我的所有服务都可以扩展它 服务接口示例 重复代码 Service public interface IUserService List
  • 为自定义驱动程序创建 GraphicsDevice

    我正在开发一个在嵌入式系统中使用 Java 的项目 我有用于屏幕和触摸输入的驱动程序 以及用于文本输入的虚拟键盘 我的屏幕驱动程序有一个Graphics2D您可以绘制的对象和repaint Rectangle 更新方法 类似地 触摸驱动器能
  • Spring数据中的本机查询连接

    我有课 Entity public class User Id Long id String name ManyToMany List
  • 如何检测图像是否像素化

    之前有人在 SO 上提出过这样的问题 在Python中检测像素化图像 https stackoverflow com questions 12942365 detecting a pixelated image in python还有关于q
  • 是否可以从 servlet 内部以编程方式设置请求上下文路径?

    这是一个特殊情况 我陷入了处理 企业 网络应用程序的困境 企业应用程序正在调用request getContext 并将其与另一个字符串进行比较 我发现我可以使用 getServletContext getContextPath 获取 se
  • 如何使用正则表达式验证 1-99 范围?

    我需要验证一些用户输入 以确保输入的数字在 1 99 范围内 含 这些必须是整数 Integer 值 允许前面加 0 但可选 有效值 1 01 10 99 09 无效值 0 007 100 10 5 010 到目前为止 我已经制定了以下正则
  • 虽然我的类已加载,但 Class.forName 抛出 ClassNotFoundException

    代码如下 它的作用是加载我放在主目录中的 jar 文件中的所有类 import java io File import java util jar JarFile import java util jar JarEntry import j
  • Java:如何确定文件所在的驱动器类型?

    Java 是否有一种独立于平台的方法来检测文件所在的驱动器类型 基本上我有兴趣区分 硬盘 可移动驱动器 如 USB 记忆棒 和网络共享 JNI JNA 解决方案不会有帮助 可以假设 Java 7 您可以使用 Java 执行 cmd fsut
  • 如何通过 Android 按钮单击运行单独的应用程序

    我尝试在 Android 应用程序中添加两个按钮 以从单独的两个应用程序订单系统和库存系统中选择一个应用程序 如图所示 我已将这两个应用程序实现为两个单独的 Android 项目 当我尝试运行此应用程序时 它会出现直到正确选择窗口 但是当按
  • 如何停止执行的 Jar 文件

    这感觉像是一个愚蠢的问题 但我似乎无法弄清楚 当我在 Windows 上运行 jar 文件时 它不会出现在任务管理器进程中 我怎样才能终止它 我已经尝试过 TASKKILL 但它对我也不起作用 On Linux ps ef grep jav
  • JAVA中遍历JSON数据

    我是 JSON 新手 我使用 HTTPUrlConnections 并在 JAVA 程序中获得一些响应 响应数据将类似于 data id 1 userId 1 name ABC modified 2014 12 04 created 201
  • Play.application() 的替代方案是什么

    我是 Play 框架的新手 我想读取conf文件夹中的一个文件 所以我用了Play application classloader getResources Data json nextElement getFile 但我知道 play P
  • 使用Java绘制维恩图

    我正在尝试根据给定的布尔方程绘制维恩图 例如 a AND b AND c我想在 Android 手机上执行此操作 因此我需要找到一种使用 Java 来执行此操作的方法 我找到了一个完美的小部件 它可以完成我在这方面寻找的一切布尔代数计算器
  • 禁用 Android 菜单组

    我尝试使用以下代码禁用菜单组 但它不起作用 菜单项仍然启用 你能告诉我出了什么问题吗 资源 菜单 menu xml menu menu
  • 即使调整大小,如何获得屏幕的精确中间位置

    好的 这个问题有两部分 当我做一个JFrame 并在其上画一些东西 即使我将宽度设置为 400 并使其在一个项目击中它时 当然 允许项目宽度 它会反弹回来 但由于某种原因 它总是偏离屏幕约 10 个像素 有没有办法解决这个问题 或者我只需要

随机推荐

  • C语言中如何使用字符数组和字符型指针变量

    案例一 使用字符数组统计字符串的长度以及实现字符串的反转 参考代码 xff1a include lt stdio h gt include lt stdlib h gt include lt string h gt int main cha
  • 拓扑排序详解

    提示 xff1a 古人学问无遗力 少壮功夫老始成 xff0c 纸上得来终觉浅 觉知此事须躬行 文章目录 一 AOV网的特点二 问题三 拓扑排序四 拓扑排序的方法五 检查AOV网中是否存在一个环六 两种思路6 1 思路一6 1 1 思路一代码
  • Altium Designer——设置电源线规则

    1 创建类来新建规则 执行菜单Design Classes 快捷键DC 将这多个网络建立一个class 执行菜单命令Design Rules 快捷键DR xff09 xff0c 进入规则设置栏 xff1b 新建个线宽规则 xff0c 在规则
  • 【Archlinux】(3) —— dwm+st+firefox+fcitx=愉快上网

    Archlinux dwm 43 st 43 firefox 43 fcitx 61 愉快上网 1 dwm窗口管理器2 ST简单终端3 firefox浏览器4 fcitx中文输入法参考资料 注意 后的命令是root用户和普通用户均可以的操作
  • idea创建maven项目产生卡死问题

    2021版idea创建maven项目时卡死问题解决 xff1a 问题描述 xff1a 在file project structure中新建maven的modules时 xff0c 点击finish后idea会卡死 xff0c 其他人有的说要
  • SpringBoot配置环境

    typora copy images to upload 微服务架构 第一个Spring Boot程序 jdk 1 8maven 3 6 1springboot 最新版IDEA 修改端口号 banner banner在线制作网站 Sprin
  • 【坑】导入项目报错Could not find com.android.tools.build:gradle:7.4.0

    报错的图没得了 xff0c 反正就是Could not find com android tools build gradle 7 4 0 这个报错解决思路 xff1a 1 首先导入项目你不要直接File Open xff0c 你要FIle
  • 通过adb命令安装卸载apk

    一 安装apk xff1a 1 正常安装APK adb install xxxx apk 2 覆盖安装APK adb install r xxxx apk 2 安装测试APK adb install t xxxx apk 3 组合使用 ad
  • 使用VNC远程连接云服务器,连接超时问题

    这里用的本地VNC工具为VNC viewer xff0c 使用的服务器为腾讯云CentOS服务器 已经在服务器端完成了图形化界面的安装以及开启vncserver xff0c 但是无法连接 已经创建完成vnc的服务器端 开启vnc命令 vnc
  • Spring框架的知识整理(项目流程)以及SSM框架的整合

    前言 上一篇文章我们发表Mybatis框架的学习心得 xff0c 以及针对一个项目而言说了一些流程 Spring学习的时候我们需要知道它的两个核心功能Ioc Aop xff0c 本文今日对Ioc做重点解释 Ioc功能阐述 Ioc 主要是一个
  • Ubuntu安装文件

    安装Java 首先在官网下载linux版本的jdk 然后传给linux xff0c 在解压到 usr local目录下 xff0c 在进入 url local目录 xff0c 并完成环境配置 tar zxvf jdk 8u331 linux
  • 快速排序(java实现)

    快速排序的思想 在一个无序的数组中 xff0c 取最后的一个数字为基准值 xff0c 在经过一次排序后 xff0c 使得改无效而的数组中 xff0c 小于基准值的在左侧 xff0c 等于基准值的在中间 xff0c 大于基准值的在右侧 假设一
  • 使用websocket实现服务端主动发送消息到客户端

    平时我们都是由客户端浏览器主动发送请求到服务端 xff0c 然后服务器处理请求后返回结果 xff0c 服务器无法主动向客户端浏览器发送消息 但是在某些业务场景下我们需要由服务器主动发送消息到客户端浏览器 xff0c 如当客户用户下订单后 x
  • Day01-Vue的基本格式

    创建Vue实例传入的options 我们在创建Vue的时候 xff0c 会传入一个对象options 这个options包含哪些选项 xff1f 目前掌握这些选项 el 类型 xff1a string HTMLElement xff08 表
  • LAMP架构超详细搭建步骤

    LAMP介绍 xff1a Linux 43 Apache 43 Mysql MariaDB 43 Perl PHP Python一组常用来搭建或者服务器的开源软件 xff0c 本身都是各自独立的程序 xff0c 但是因为常被放在一起使用 x
  • ViewBinding的简单使用

    我们知道ButterKnife已经过时 首先开启viewBinding xff1a android viewBinding enabled 61 true 之后在Activity中操作 span class token keyword pa
  • linux系统下防火墙的使用以及开通端口

    1 基本使用 启动 xff1a systemctl start firewalld 关闭 xff1a systemctl stop firewalld 查看状态 xff1a systemctl status firewalld 开机禁用 x
  • 如何让自己电脑的cmd看起来更美观

    一 快速切换cmd字体颜色 xff08 暂时性 xff09 打开cmd输入color 02 二 永久性切换cmd文字颜色 打开cmd xff0c 在标题栏处鼠标右键选择属性 选择颜色 xff0c 切换自己喜欢的颜色 xff0c 点击确定即可
  • Android 音频开发——Radio Hal服务(三)

    nbsp nbsp nbsp nbsp nbsp nbsp nbsp 上一篇文章主要介绍了 BroadcastRadioService 的启动 这一篇我们介绍以下Radio Hal 层的服务 一 Radio模块的加载 nbsp nbsp n
  • java锁策略和synchronized锁机制

    一 常见的锁策略 1 乐观锁 vs 悲观锁 锁的实现者 xff0c 预测接下来的锁冲突概率大不大 xff0c 根据这个概率决定接下来该做什么 乐观锁 xff1a 预测冲突不大 xff0c 做的工作少一些 xff0c 效率更高一些 悲观锁 x