乐观锁和悲观锁的区别 使用 使用场景 | 图解

图解乐观锁和悲观锁的区别 & 实现 & 使用场景

文章目录

  • 图解乐观锁和悲观锁的区别 & 实现 & 使用场景
    • 悲观锁
      • synchronized 与 ReentrantLock
    • 乐观锁
      • CAS 机制
      • 版本号机制
      • 原子类
    • 总结两种锁各自的使用场景

悲观锁

悲观主义者,认为这个资源不上锁,就一定会别的线程来争抢,造成数据错误

  • 它每次操作资源都会上锁

  • 共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程

  • 像 Java 中synchronizedReentrantLock等独占锁就是悲观锁思想的实现

在这里插入图片描述

synchronized 与 ReentrantLock

使用 synchronized 修饰代码块:

public void method() {// 加锁代码synchronized (this) {// ...}
}

ReentrantLock 在使用之前需要先创建 ReentrantLock 对象,然后使用 lock 方法进行加锁,使用完之后再调用 unlock 方法释放锁,具体使用如下:

public class LockExample {// 创建锁对象private final ReentrantLock lock = new ReentrantLock();public void method() {// 加锁操作lock.lock();try {// ...} finally {// 释放锁lock.unlock();}}
}

乐观锁

乐观主义者,不担心没有发生的事,在修改数据不会上锁,但会判断与预期的是否一致。

  • 在提交修改的时候去验证对应的资源是否被其它线程修改了,就不去修改了【不会锁住被操作对象,不会不让别的线程来接触它】,如在MySQL中加个version字段(版本号机制)
  • 在 Java 中juc.atomic包下面的原子变量类(比如AtomicIntegerLongAdder)就是使用了乐观锁的一种实现方式 CAS 实现的。

在这里插入图片描述

CAS 机制

CAS 机制 是 Java 中 Unsafe 类中的一个方法,全称是 CompareAndSwap 比较交换的意思。它用于多线程下对共享变量修改的一个原子性。

CAS 涉及到三个操作数:

  • E:预期值(Expected)
  • V:要更新的当前变量值(Var)
  • N:拟写入的新值(New)

当且仅当 V 的值等于 E 时,CAS 通过原子方式用新值 N 来更新 V 的值。如果不等,说明已经有其它线程更新了 V,则当前线程放弃更新。


如下图,该线程要修改变量的值为 1,变量原来的值为 0

也就是 【V=0,E=0,N=1】

  • 线程 与 0 进行比较,如果相等, 则说明没被其他线程修改,可以被设置为 1
  • 线程 与 0 进行比较,如果不相等,则说明被其他线程修改,当前线程放弃更新,CAS 操作失败

在这里插入图片描述

版本号机制

在数据库中新增 version 列,代表版本号,通过版本号是否与之前的一致来判断数据是否被修改过。

  • 当读取数据时,会同时读取版本号。
  • 当更新数据时,会检查版本号是否发生变化。如果版本号与读取时的版本号一致,说明在此期间没有其他线程修改过数据,那么更新操作可以成功执行;如果版本号不一致,则说明数据已经被其他线程修改,此时需要重新读取数据并尝试更新。

如下图,user1 和 user2 同时在操作 id = 1 的数据,在修改这条数据时,会判断版本号是否一致,由于 user1 先修改成功了,并且把 version 自增了,所以 user2 的 version 与一开始查询的不一致会更新失败。

这样就能保证在多线程环境操作共享资源安全的问题,本质还是依靠数据库底层的排它锁实现的。

在这里插入图片描述

原子类

原子类是具有原子性的类,原子性的意思是对于一组操作,要么全部执行成功,要么全部执行失败,不能只有其中某几个执行成功,它的底层也是用到了 CAS 机制。

在JDK中J.U.C包下提供了种类丰富的原子类。

详情:菜鸟教程 - java.util.concurrent.atomic (Java SE 11 & JDK 11 )

以下用常用的AtomicInteger作为演示:

import java.util.concurrent.atomic.AtomicInteger;public class AtomicIntegerDemo {private static final int THREADS_CONUT = 20;public static AtomicInteger count = new AtomicInteger(0);public static void increase() {count.incrementAndGet();}public static void main(String[] args) {Thread[] threads = new Thread[THREADS_CONUT];for (int i = 0; i < THREADS_CONUT; i++) {threads[i] = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 1000; i++) {increase();}}});threads[i].start();}while (Thread.activeCount() > 1) {Thread.yield();}System.out.println(count);}
}

总结两种锁各自的使用场景

  • 悲观锁适用于并发写入多、竞争激烈场景,避免无用尝试。
  • 乐观锁适用于多读少写或并发不激烈场景,提高性能。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Linux初步引言(0)

文章目录 前言一、发展史UNIX发展史Linux发展史 二、开源精神三、Linux内核官网四、企业应用现状在服务器领域的发展在桌面领域的发展在移动嵌入式的发展Linux在云计算/大数据领域的发展 五、众多的发行版本DebianUbuntuCentOSKail Linux 六、何为操作系统&#xff1f;总结 前言…

Linux: C语言发起 DNS 查询报文

本文目录 使用 getaddrinfo()手动构造 DNS 查询报文DNS 查询部分&#xff08;Question Section&#xff09;QNAME (查询的域名)QTYPE (查询类型)QCLASS (查询类)Answer Section (答案部分) C语言代码发起 DNS 查询报文 使用 getaddrinfo() getaddrinfo() 是一个高层的接口&…

【Pytorch】神经网络介绍|激活函数|使用pytorch搭建方法

神经网络 神经网络介绍 概念 神经网络 人工神经网络ANN 也称神经网络NN 是一种模仿生物神经网络结构和功能的计算模型人脑可以看作是一个生物神经网络,由众多神经元连接而成,神经网络可以看作是模拟生物神经元的过程 输入层 input Layer: 输入x的那一层 输出层 output Laye…

【HarmonyOS NEXT】实战——登录页面

【HarmonyOS NEXT】实战——登录页面 在本文中&#xff0c;我们将深入探讨如何使用HarmonyOS NEXT来实现一个功能完备的登录页面。通过这个实战案例&#xff0c;你将结合页面布局、数据本地化存储、网络请求等多方面了解到HarmonyOS NEXT在构建现代应用时的强大能力和灵活性。…

iscc2023

iscc 还没想好名字的塔防游戏 就是那句话首字母&#xff0c;加上玩游戏通关后有提示就是后面的字母 Flask中的pin值计算 先f12&#xff0c;看到base64到路由/getusername 输入app.py&#xff0c;得到路由/crawler 进入后发现是一个计算&#xff0c;写一个python脚本 impor…

力扣-Mysql-3328-查找每个州的城市 II(中等)

一、题目来源 3328. 查找每个州的城市 II - 力扣&#xff08;LeetCode&#xff09; 二、数据表结构 表&#xff1a;cities ---------------------- | Column Name | Type | ---------------------- | state | varchar | | city | varchar | ----------------…

Vue2:组件

Vue2&#xff1a;组件 非单文件组件定义注册使用 单文件组件 组件是Vue中最核心的内容&#xff0c;在编写页面时&#xff0c;将整个页面视为一个个组件&#xff0c;再把组件拼接起来&#xff0c;这样每个组件之间相互独立&#xff0c;有自己的结构样式&#xff0c;使页面编写思…

力扣 LeetCode 28. 找出字符串中第一个匹配项的下标(Day4:字符串)

解题思路&#xff1a; KMP算法 需要先求得最长相等前后缀&#xff0c;并记录在next数组中&#xff0c;也就是前缀表&#xff0c;前缀表是用来回退的&#xff0c;它记录了模式串与主串(文本串)不匹配的时候&#xff0c;模式串应该从哪里开始重新匹配。 next[ j - 1 ] 记录了 …

计算机网络 (1)互联网的组成

一、互联网的边缘部分 互联网的边缘部分由所有连接在互联网上的主机组成&#xff0c;这些主机又称为端系统&#xff08;end system&#xff09;。端系统可以是各种类型的计算机设备&#xff0c;如个人电脑、智能手机、网络摄像头等&#xff0c;也可以是大型计算机或服务器。端系…

智慧军营安防方案

1. 引言 智慧安防方案集成高清视频监控、智能分析与大数据管理&#xff0c;打造全方位安全防护体系。通过先进技术&#xff0c;提升预警与应急响应能力&#xff0c;确保安全无死角。 2. 视频监控技术 采用高清摄像设备与智能识别算法&#xff0c;实现全景监控与细节跟踪&#…

ABAP开发学习——ST05 ABAP SQL跟踪工具

操作步骤 第一步使用ST05之前&#xff0c;将要查的程序停留想要看的操作的前一步&#xff0c;这里想看到取数操作&#xff0c;所以停留在选择界面 第二步进入ST05 选择SQL Trace 然后激活 第三步去执行程序 第四步ST05取消激活 第五步查看操作 选完时间直接执行

AtCoder ABC378 A-D题解

比赛链接:ABC378 比较简单的一次 ABC。 Problem A: Code #include <bits/stdc.h> using namespace std; int main(){cin>>A[1]>>A[2]>>A[3]>>A[4];sort(A1,A5);if(A[1]A[2] && A[3]A[4])cout<<2<<endl;else{if(A[1]A[2]…

Windows上安装专业版IDEA2024并激活

1、IDEA官方下载 搜索IDEA官网点击进入&#xff0c;点击Download&#xff08;目前这个激活脚本只能激活2024.1.7&#xff0c;2024.2.x的版本都不能激活&#xff0c;2024.1.7版本已上传资源&#xff09;&#xff0c;如图&#xff1a; 2、开始安装 1&#xff09;、双击下载的.…

表达式求值问题(中缀转后缀,对后缀求值)详解

目录 实验题目 理解中缀和后缀表达式 问题分析 1转化为中缀表达式 2计算后缀表达式 完整代码 运行结果 实验题目 实验题目&#xff1a;表达式求值问题。这里限定的表达式求值问题是&#xff1a; 用户输入一个包含“”、“-”、“*”、“/”、正整数和圆括号的合法数学表…

AD22怎么按照板子形状铺铜

如何按照板子形状来铺铜&#xff1f; 选择铺铜管理器 选择板外形 我这里图里VCC没画就选择VCC&#xff0c; 你选什么层&#xff0c;就勾什么层 死铜移除勾选 效果如下&#xff1a;

【视觉SLAM】2-三维空间刚体运动的数学表示

读书笔记&#xff1a;学习空间变换的三种数学表达形式。 文章目录 1. 旋转矩阵1.1 向量运算1.2 坐标系空间变换1.3 变换矩阵与齐次坐标 2. 旋转向量和欧拉角2.1 旋转向量2.2 欧拉角 3. 四元数 1. 旋转矩阵 1.1 向量运算 对于三维空间中的两个向量 a , b ∈ R 3 a,b \in \R^3 …

研发费用资本化的意义

1.更真实地反映企业价值&#xff1a;研发费用是企业为创造未来经济利益而进行的投资&#xff0c;通过将其资本化并作为无形资产计入资产负债表&#xff0c;可以更真实地反映企业的资产总额和长期投资价值。这有助于投资者、债权人和其他利益相关者更准确地评估企业的财务状况、…

Ubuntu24.04安装Anaconda3+Pycharm

一、引言 重装系统已经过去一段时间了&#xff0c;现在安装一下 Anaconda 和 Pycharm。 参考连接&#xff1a; Ubuntu中安装Anaconda3和Pycharm 及其环境搭建Ubuntu18.04安装Pycharm教程ubuntu系统安装Anaconda及Pycharm在移动硬盘上搭建Ubuntu24.04深度学习环境&#xff08;…

稀疏矩阵(Sparse Matrix)及其存储格式详解

稀疏矩阵&#xff08;Sparse Matrix&#xff09;是线性代数和计算机科学中的一个重要概念&#xff0c;广泛应用于科学计算、工程模拟、图像处理、机器学习等多个领域。与稠密矩阵&#xff08;Dense Matrix&#xff09;相比&#xff0c;稀疏矩阵大部分元素为零&#xff0c;仅有少…

操作系统:页表中的页表项

操作系统&#xff1a;页表中的页表项 页表是操作系统用于跟踪进程使用的虚拟地址与系统内存中相应物理地址之间映射的数据结构。 页表项&#xff08;Page Table Entry&#xff0c;PTE&#xff09;是页表中的一个条目&#xff0c;用于存储有关特定内存页的信息。每个页表项包含…