关于锁策略

    • 常见的锁策略
      • 悲观锁
      • 乐观锁
      • 读写锁
      • 轻量级锁、重量级锁
      • 自旋锁
      • 公平锁和非公平锁
      • 可重入锁 vs 不可重入锁
      • synchronized是什么锁呢?

常见的锁策略

锁策略不仅仅限制于Java;其它锁相关的也是会涉及这些策略;这些特性主要是在实现锁的时候运用的。虽然我们的工作可能就是把轮子拼装成一辆车;不涉及造一个轮子。但是背后的原理学习还是有利于我们对知识的理解和深入;能初步的认识。

悲观锁

定义:假设在并发环境中都会发生冲突,因此在访问共享资源之前先获取锁。统统阻塞;得先获取锁。

乐观锁

定义:假设在并发环境中都不会发生冲突,因此直接进行操作,而在更新时检查是否有其他线程干扰。如果发现并发冲突了,则让返回用户错误的信息,让用户决定如何去做。

1:悲观与乐观区别?
预测锁竞争激励程度;然后背后的处理是不同的。

2:乐观锁如何检查是否有其它线程干扰呢?
乐观锁处理:是在进行操作(读或写)时不显式加锁,而是通过某种机制(如版本号、时间戳、CAS操作等)在更新时检查是否有其他线程干扰。
假设:设我们需要多线程修改 “用户账户余额”;设当前余额为 100. 引入一个版本号 version, 初始值为 1. 规定 “提交版本必须大于记录当前版本才能执行更新余额”
在这里插入图片描述

读写锁

区分读操作和写操作,允许多个线程同时读取共享资源,但只有一个线程可以进行写操作。

1:为什么能对读写锁区分呢?
一个线程对于数据的访问, 主要存在两种操作: 读数据和写数据.
两个线程都只是读一个数据, 此时并没有线程安全问题. 直接并发的读取即可.
两个线程都要写一个数据, 有线程安全问题.
一个线程读另外一个线程写, 也有线程安全问题.

2:Java 标准库提供了 ReentrantReadWriteLock 类, 实现了读写锁.
ReentrantReadWriteLock.ReadLock 类表示一个读锁. 这个对象提供了 lock / unlock 方法进行
加锁解锁.
ReentrantReadWriteLock.WriteLock 类表示一个写锁. 这个对象也提供了 lock / unlock 方法进
行加锁解锁.

3:读锁跟写锁的区别

  1. 读锁(共享锁):
    a:多线程读取时不互斥:多个线程可以同时获得读锁,同时读取共享资源,不互斥。
    b:适用于读多写少场景:在读多写少的场景中,多个线程可以同时读取共享资源,提高并发性能。
    c:阻塞写操作:当一个线程持有读锁时,其他线程若想获得写锁,就会被阻塞,直到所有的读锁都被释放。
    d:不阻塞读操作:读锁不会阻塞其他读操作,因为多个线程可以同时持有读锁。

  2. 写锁(排它锁):
    a:互斥访问:写锁是独占锁,同一时刻只允许一个线程持有写锁,用于保护对共享资源的写操作。
    b:适用于写多读少场景:在写多读少的场景中,写锁能够确保只有一个线程能够修改共享资源,保证数据的一致性。
    c:阻塞其他写操作和读操作:当一个线程持有写锁时,其他线程若想获得读锁或写锁,都会被阻塞,直到写锁被释放。
    d:不允许陈旧的读操作:写锁的引入确保在写操作时不会有其他读或写操作,防止产生陈旧的读操作结果。

轻量级锁、重量级锁

因为锁是操作系统对CPU的原子指令实现mutex 互斥锁;我们JVM 基于操作系统提供的互斥锁, 实现了 synchronized 和 ReentrantLock 等关键字和类.;但是基于mutex 进行封装;但是不限于这些工作。

轻量级锁:轻量级锁是为了在多线程竞争不激烈的情况下提高性能而设计的。不太依赖操作系统的mutex;不容易引发线程的调度;线程状态切换也是要开销的。

重量级锁:重量级锁是为了在多线程竞争激烈的情况下保证数据的正确性而设计的。重度依赖操作系统mutex;很容易引发线程的调度;线程状态切换也是要开销的。

自旋锁

按之前的方式,线程在抢锁失败后进入阻塞状态,放弃 CPU,需要过很久才能再次被调度;大部分情况下,虽然当前抢锁失败,但过不了很久,锁就会被释放。没必要就放弃 CPU. 这个时候就可以使用自旋锁来处理这样的问题。
自旋锁一种忙等的状态;如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试会在极短的时间内到来.;一旦锁被其他线程释放, 就能短时间获取到锁.
伪代码:
在这里插入图片描述
自旋锁是一种典型的轻量级锁的实现方式:
优点: 没有放弃 CPU, 不涉及线程阻塞和调度, 一旦锁被释放, 就能第一时间获取到锁.
缺点: 如果锁被其他线程持有的时间比较久, 那么就会持续的消耗 CPU 资源. (而挂起等待的时候是
不消耗 CPU 的)

公平锁和非公平锁

假设三个线程 A, B, C.。A 先尝试获取锁, 获取成功. 然后 B 再尝试获取锁, 获取失败, 阻塞等待; 然后
C 也尝试获取锁, C 也获取失败, 也阻塞等待.
公平锁: 遵守 “先来后到”. B 比 C 先来的. 当 A 释放锁的之后, B 就能先于 C 获取到锁.
非公平锁: 不遵守 “先来后到”. B 和 C 都有可能获取到锁.
操作系统调度上随机的;可以看做默认是非公平锁;想实现公平锁, 就需要依赖额外的数据结构, 来记录线程们的先后顺序.

可重入锁 vs 不可重入锁

可重入锁的字面意思是“可以重新进入的锁”,即允许同一个线程多次获取同一把锁。
Java里只要以Reentrant开头命名的锁都是可重入锁,而且JDK提供的所有现成的Lock实现类,包括
synchronized关键字锁都是可重入的。而 Linux 系统提供的 mutex 是不可重入锁

synchronized是什么锁呢?

synchronized是悲观锁也是乐观锁:
初始使用乐观锁策略. 当发现锁竞争比较频繁的时候, 就会自动切换成悲观锁策略.
Synchronized 不是读写锁
synchronized是轻量级锁也是重量级锁;如果锁冲突比较严重, 就会变成重量级锁。和悲观乐观锁对锁的预测程度是不同。
synchronized 是非公平锁:基于操作系统的 mutex实现
synchronized 是可重入锁:通过记录持有锁的线程身份和计数器记录加锁次数。 如果发现当前加锁
的线程就是持有锁的线程, 则直接计数自增。要所有的锁释放才能被别人获取到;即计数器为0。

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

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

相关文章

virtualBox虚拟机局域网访问配置

在VirtualBox中,桥接网络是一种网络连接类型,它允许虚拟机连接到物理网络上的路由器或交换机,在物理网络上获得独立的网络地址和访问权限。 一、设置VirtualBox桥接网络的步骤: 打开VirtualBox软件,并选择你想要配置…

FPGA运算

算数运算中,输入输出的负数全用补码来表示,例如用三位小数位来表示的定点小数a-1.625和b-1.375。那么原码分别为a6b‘101101, b6b101011, 补码分别是a6’b110011,b6‘b110101; 如果想在fpga中实现a*b,则需要将a和b用补…

文件夹批量改名:实用技巧,如何快速删除文件夹名称中的数字

在我们的日常生活和工作中,文件夹命名经常会包含一些数字,这些数字可能是在文件夹创建时自动添加的,也可能是为了方便我们识别而手动添加的。然而,有时候这些数字可能会变得不再必要,或者我们想要删除它们以使文件夹名…

浅聊反射系数——为何有共轭?

文章目录 1、基于行波理论的行波反射系数2、共轭匹配与功率波反射系数3、总结 不知道大家是否有和我一样,有下列疑惑:为什么反射系数定义中分子有的时候存在共轭,有的时候又没有共轭。比如: 通俗解释就是:一般来说&…

IDEA 使用Reset Current Branch to Here 进行git 版本控制,图文操作

文章目录 一、总结区别(只针对本地仓库操作)Soft详细解释文件版本冲突处理 Mixed详细解释Hard详细解释Keep详细解释文件版本冲突处理 二、其他Revert commit 参考文档 一、总结区别(只针对本地仓库操作) Soft详细解释 Soft操作只…

Spring高手之路16——解析Spring XML配置的BeanDefinition源码

文章目录 1. BeanDefinition阶段的分析2. 加载xml配置文件2.1 XML配置文件中加载bean的代码示例2.2 setConfigLocations - 设置和保存配置文件路径2.3 refresh - 触发容器刷新,配置文件的加载与解析2.4 loadBeanDefinitions - 具体的BeanDefinition加载逻辑2.5 load…

分享Python的十大库,这你一定得知道!

文章目录 前言关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 前言 Python为我们提供了非常完善的基础库&#…

适用于4D毫米波雷达的目标矩形框聚类

目录 一、前言 二、点云聚类分割 三、基于方位搜索L型拟合 四、评价准则之面积最小化 五、评价准则之贴合最大化 六、评价准则之方差最小化 一、前言 对于多线束雷达可以获取目标物体更全面的面貌,在道路中前向或角雷达可能无法获取目标车矩形框但可以扫到两边…

《算法通关村——二分查找在旋转数字中的应用》

《算法通关村——二分查找在旋转数字中的应用》 这里我们直接通过一个题目,来了解二分查找的应用。 153. 寻找旋转排序数组中的最小值 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如&a…

ios开发 之 多线程

目录 第一节:多线程简介 线程执行原理 主线程 多线程解决方案 pthread __bridge NSThread 线程的状态 第二节:多线程访问资源 Synchronized nonatomic 、atomic 自动释放池 属性修饰符 第三节:消息循环 消息模式 第四节&…

Kubernetes 创建pod的yaml文件-简单版-nginx

apiVersion: v1 #api文档版本 kind: Pod # 资源类型 Deployment,StatefulSet之类 metadata: #pod元数据 描述信息 name: nginx-demo labels: type: app #自定义标签 version: 1.0.0 # 自定义pod版本 namespace: default spec: #期望Pod按照这里的描述创建 cont…

React进阶之路(三)-- Hooks

文章目录 Hooks概念理解什么是HooksHooks解决了什么问题 useState基础使用状态的读取和修改组件的更新过程使用规则回调函数作为参数 useEffect什么是函数副作用基础使用依赖项控制执行时机清理副作用发送网络请求 useRefUseContext Hooks概念理解 什么是Hooks Hooks的本质&am…

防火墙部署模式 -- 单臂路由模式

防火墙单臂路由部署模式 如图,PC 1与PC 2通信,想在中间加上防火墙对其进行监控,并实现对两台设备的通信阻断,可以在交换机的另一个接口上连接防火墙,交换机将两台PC发送的数据引流到防火墙上,防火墙也配置下…

LeetCode 118. 杨辉三角 简单

题目 - 点击直达 1. 118. 杨辉三角 简单1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. 118. 杨辉三角 简单 1. 题目详情 给定一个非负整数 numRows,生成「杨辉三角」的前 n u m R o w s numRows numRows 行。…

sqli-bypass wp

sqli-bypass靶场 level 1 尝试注入点 1 ,1,1,1",1"" 》存在字符型单引号注入 id1and(1)-- >提示存在sql注入 bypass and、()、--都可能存在被屏蔽掉 尝试#代替-- id1and(1)%23 》 正常回显,说明–被屏蔽了,and&#xf…

Python+Appium自动化测试-编写自动化脚本

一,连接测试手机,获取测试机及被测APP配置 配置信息如下: {"platformName": "Android","platformVersion": "10","deviceName": "PCT_AL10","appPackage": "c…

查找或替换excel换行符ctrl+j和word中的换行符^p,^l

一、excel中 直接上图。使用ctrlh调出替换,查找内容里按ctrlj(会出现一个闪的小点),即为换行符。 二、word中 在word中,^p和^l分别代表换行符(enter)和手动换行符(使用shiftenter&…

Python最基础的五个部分代码,零基础也能轻松看懂。

文章目录 前言一、表达式二、赋值语句三、引用四、分支语句五、循环语句关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼…

opencv dnn模块 示例(22) 目标检测 object_detection 之 yolov7

在YOLOv6 初版出来不久,YOLOv7就立马横空出世了。与YOLOv5、YOLOv6不同,YOLOv7是由YOLOv4团队的原班人马提出的(官方出品)。从论文的表上来看,目前YOLOv7无论是在实时性还是准确率上都已经超过了当时已知的所有目标检测…

【考研数据结构代码题4】求树中度为1的结点数(递归方式)

题目:用C语言描述树的孩子兄弟链表结构,并编写递归程序求树中度为1的结点数 难度:★★ 算法思路:递归地遍历当前结点的左孩子子树与右兄弟子树,分别求二者中度为1的结点数记为h1,h2,若当前结点仅有1个结点,…