前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >悲观锁和乐观锁

悲观锁和乐观锁

作者头像
ha_lydms
发布于 2023-08-09 12:57:22
发布于 2023-08-09 12:57:22
21300
代码可运行
举报
文章被收录于专栏:学习内容学习内容
运行总次数:0
代码可运行

一、什么是悲观锁,什么是乐观锁

1、锁(Lock)

 在介绍悲观锁和乐观锁之前,让我们看一下锁。锁,在我们生活中随处可见,我们的门上有锁,我们存钱的保险柜上有锁,是用来保护我们财产安全的。程序中也有锁,当多个线程修改共享变量时,我们可以给修改操作上锁(syncronized)。当多个用户修改表中同一数据时,我们可以给该行数据上锁(行锁)。

因此,锁其实是在并发下控制多个操作的顺序执行,以此来保证数据安全的变动。 并且,锁是一种保证数据安全的机制和手段,而并不是特定于某项技术的。悲观锁和乐观锁亦是如此。

2、悲观锁(Pessimistic Concurrency Control):

 悲观锁,第一眼看到它,相信每个人都会想到这是一个悲观的锁。没错,它就是一个悲观的锁。那这个悲观体现在什么地方呢?悲观是我们人类一种消极的情绪,对应到锁的悲观情绪。悲观锁认为被它保护的数据是极其不安全的,每时每刻都有可能变动,一个事务拿到悲观锁后(可以理解为一个用户),其他任何事务都不能对该数据进行修改,只能等待锁被释放才可以执行。 数据库中的行锁,表锁,读锁,写锁,以及syncronized实现的锁均为悲观锁。

3、乐观锁(Optimistic Concurrency Control):

 与悲观相对应,乐观是我们人类一种积极的情绪。乐观锁的“乐观情绪”体现在,它认为数据的变动不会太频繁。因此,它允许多个事务同时对数据进行变动。 但是,乐观不代表不负责,那么怎么去负责多个事务顺序对数据进行修改呢?乐观锁通常是通过在表中增加一个版本(version)或时间戳(timestamp)来实现,其中,版本最为常用。  事务在从数据库中取数据时,会将该数据的版本也取出来(v1),当事务对数据变动完毕想要将其更新到表中时,会将之前取出的版本v1与数据中最新的版本v2相对比,如果v1=v2,那么说明在数据变动期间,没有其他事务对数据进行修改,此时,就允许事务对表中的数据进行修改,并且修改时version会加1,以此来表明数据已被变动。如果,v1不等于v2,那么说明数据变动期间,数据被其他事务改动了,此时不允许数据更新到表中,一般的处理办法是通知用户让其重新操作。不同于悲观锁,乐观锁是人为控制的。

二、怎么实现悲观锁,怎么实现乐观锁

经过上面的学习,我们知道悲观锁和乐观锁是用来控制并发下数据的顺序变动问题的。那么我们就模拟一个需要加锁的场景,来看不加锁会出什么问题,并且怎么利用悲观锁和乐观锁去解决。

场景: A和B用户最近都想吃猪肉脯,于是他们打开了购物网站,并且找到了同一家卖猪肉脯的>店铺。下面是这个店铺的商品表goods结构和表中的数据

id

name

num

1

猪肉脯

1

2

牛肉干

1

从表中可以看到猪肉脯目前的数量只有1个了。在不加锁的情况下,如果A,B同时下单,就会报错。

1、悲观锁解决

利用悲观锁的解决思路是,A下单前先给猪肉脯这行数据(id=1)加上悲观锁(行锁)。此时这行数据只能A来操作,也就是只有A能买。B想买就必须一直等待。当A买好后,B再想去买的时候会发现数量已经为0,那么B看到后就会放弃购买。 那么如何给猪肉脯也就是id=1这条数据加上悲观锁锁呢?我们可以通过以下语句给id=1的这行数据加上悲观锁。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select num from goods where id = 1 for update;

我们通过开启mysql的两个会话,也就是两个命令行来演示。

1、事务A执行命令给id=1的数据上悲观锁准备更新数据

这里之所以要以begin开始,是因为mysql是自提交的,所以要以begin开启事务,否则所有修改将被mysql自动提交。

2、事务B也去给id=1的数据上悲观锁准备更新数据

我们可以看到此时事务B再一直等待A释放锁。如果A长期不释放锁,那么最终事务B将会报错,这有兴趣的可以去尝试一下。

3、 接着我们让事务A执行命令去修改数据,让猪肉脯的数量减一,然后查看修改后的数据,最后commit,结束事务。

我们可以看到,此时最后一个猪肉脯被A买走,只剩0个了。

4、当事务A执行完第3步后,我们看事务B中出现了什么

我们看到由于事务A释放了锁,事务B就结束了等待,拿到了锁,但是数据此时变成了0,那么B看到后就知道被买走了,就会放弃购买。 通过悲观锁,我们解决了猪肉脯购买的问题。

2、乐观锁解决

下面,我们利用乐观锁来解决该问题。上面乐观锁的介绍中,我们提到了,乐观锁是通过版本号version来实现的。 所以,我们需要给goods表加上version字段,表变动后的结构如下

id

name

num

version

1

猪肉脯

1

0

2

牛肉干

1

0

 具体的解决思路是,A和B同时将猪肉脯(id=1下面都说是id=1)的数据查出来,然后A先买,A将id=1和version=0作为条件进行数据更新,即将数量减一,并且将版本号加一。此时版本号变为1。A此时就完成了商品的购买。最后B开始买,B也将id=1和version=0作为条件进行数据更新,但是更新完后,发现更新的数据行数为0,此时就说明已经有人改动过数据,此时就应该提示用户重新查看最新数据购买。 我们还是通过开启mysql的两个会话,也就是两个命令行来演示。

1、事务A执行查询命令,事务B执行查询命令,因为两者查询的结果相同,所以下面我只列出一个截图。

此时A和B均获取到相同的数据。

2、事务A进行购买更新数据,然后再查询更新后的数据。

我们可以看到事务A成功更新了数据和版本号。

事务B再进行购买更新数据,然后我们看影响行数和更新后的数据

可以看到最终修改行数为0,数据没有改变。此时就需要我们告知用户重新处理。

三、乐观锁和悲观锁的优缺点

下面我们介绍下乐观锁和悲观锁的优缺点以便我们分析他们的应用场景,这里我只分析最重要的优缺点,也是我们要记住的。

1、悲观锁
  • 优点: 悲观锁利用数据库中的锁机制来实现数据变化的顺序执行,这是最有效的办法
  • 缺点: 一个事务用悲观锁对数据加锁之后,其他事务将不能对加锁的数据进行除了查询以外的所有操作,如果该事务执行时间很长,那么其他事务将一直等待,那势必影响我们系统的吞吐量。
2、乐观锁
  • 优点: 乐观锁不在数据库上加锁,任何事务都可以对数据进行操作,在更新时才进行校验,这样就避免了悲观锁造成的吞吐量下降的劣势。
  • 缺点: 乐观锁因为时通过我们人为实现的,它仅仅适用于我们自己业务中,如果有外来事务插入,那么就可能发生错误。

四、乐观锁和悲观锁的应用场景

悲观锁 因为悲观锁会影响系统吞吐的性能,所以适合应用在写为居多的场景下。 乐观锁 因为乐观锁就是为了避免悲观锁的弊端出现的,所以适合应用在读为居多的场景下。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【数据结构】数组和字符串(三):特殊矩阵的压缩存储:三角矩阵、对称矩阵——一维数组
  矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造成很大的空间浪费。为节约存储空间和算法(程序)运行时间,通常会采用压缩存储的方法。
Qomolangma
2024/07/30
2540
【数据结构】数组和字符串(三):特殊矩阵的压缩存储:三角矩阵、对称矩阵——一维数组
【数据结构】数组和字符串(五):特殊矩阵的压缩存储:稀疏矩阵——压缩稀疏行(CSR)
  矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造成很大的空间浪费。为节约存储空间和算法(程序)运行时间,通常会采用压缩存储的方法。
Qomolangma
2024/07/30
2710
【数据结构】数组和字符串(五):特殊矩阵的压缩存储:稀疏矩阵——压缩稀疏行(CSR)
【数据结构】数组和字符串(八):稀疏矩阵的链接存储:十字链表的创建、插入元素、遍历打印(按行、按列、打印矩阵)、销毁
  矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造成很大的空间浪费。为节约存储空间和算法(程序)运行时间,通常会采用压缩存储的方法。
Qomolangma
2024/07/30
5650
【数据结构】数组和字符串(八):稀疏矩阵的链接存储:十字链表的创建、插入元素、遍历打印(按行、按列、打印矩阵)、销毁
【数据结构】数组和字符串(十):稀疏矩阵的链接存储:十字链表的矩阵操作(加法、乘法、转置)
  矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造成很大的空间浪费。为节约存储空间和算法(程序)运行时间,通常会采用压缩存储的方法。
Qomolangma
2024/07/30
1690
【数据结构】数组和字符串(十):稀疏矩阵的链接存储:十字链表的矩阵操作(加法、乘法、转置)
【数据结构】数组和字符串(四):特殊矩阵的压缩存储:稀疏矩阵——三元组表
  矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造成很大的空间浪费。为节约存储空间和算法(程序)运行时间,通常会采用压缩存储的方法。
Qomolangma
2024/07/30
1600
【数据结构】数组和字符串(四):特殊矩阵的压缩存储:稀疏矩阵——三元组表
数据结构基础(一)数组,矩阵
有一个等式,数据结构+算法=程序,说明了数据结构对于计算机程序设计的重要性。数据结构是指数据元素的集合(或数据对象)及元素间的相互关系和构造方法。数据对象中元素之间的相互关系称为数据的逻辑结构,数据元素及元素之间关系的存储形式称为存储结构(或物理结构)。
AlbertYang
2020/09/08
1.5K0
数据结构基础(一)数组,矩阵
【数据结构】数组和字符串(七):特殊矩阵的压缩存储:三元组表的转置、加法、乘法操作
  矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造成很大的空间浪费。为节约存储空间和算法(程序)运行时间,通常会采用压缩存储的方法。
Qomolangma
2024/07/30
1950
【数据结构】数组和字符串(七):特殊矩阵的压缩存储:三元组表的转置、加法、乘法操作
文心一言 VS 讯飞星火 VS chatgpt (389)-- 算法导论25.1 2题
在许多数学和计算应用中,要求矩阵 W 的对角线元素 w_{ii} = 0 是出于特定的数学性质和算法需求。以下是一些常见的原因:
福大大架构师每日一题
2024/11/12
960
文心一言 VS 讯飞星火 VS chatgpt (389)-- 算法导论25.1 2题
【数据结构】数组和字符串(九):稀疏矩阵的链接存储:十字链表的插入、查找、删除操作
  矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造成很大的空间浪费。为节约存储空间和算法(程序)运行时间,通常会采用压缩存储的方法。
Qomolangma
2024/07/30
1150
【数据结构】数组和字符串(九):稀疏矩阵的链接存储:十字链表的插入、查找、删除操作
原 三对角矩阵
**三对角矩阵(tridiagonal):**M是一个三对角矩阵,当且仅当|i-j|>1时,M(i,j)=0。 在一个rows×rows的三对角矩阵中,非0元素排列在如下三条对角线上: 1)主对角
青木
2018/05/28
1.1K0
盘一盘 Python 特别篇 20 - SciPy 稀疏矩阵
和稠密矩阵相比,稀疏矩阵的最大好处就是节省大量的内存空间来储存零。稀疏矩阵本质上还是矩阵,只不过多数位置是空的,那么存储所有的 0 非常浪费。稀疏矩阵的存储机制有很多种 (列出常用的五种):
用户5753894
2020/08/06
2.1K0
leetcode-766-Toeplitz Matrix(每一条对角线元素的比较)
题目描述: A matrix is Toeplitz if every diagonal from top-left to bottom-right has the same element. Now given an M x N matrix, return True if and only if the matrix is Toeplitz. Example 1: Input: matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]] Output: True Explana
chenjx85
2018/05/21
7550
小白的机器学习实战——向量,矩阵和数组 小白的机器学习实战——向量,矩阵和数组
创建矩阵 import numpy as np # 创建矩阵 matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) 向量 # 行向量 vector_row = np.array([1, 2, 3]) # 列向量 vector_column = np.array([[1],
尾尾部落
2018/09/04
1.1K0
【数据结构】串与数组
文章目录 4. 串与数组 4.1 串概述 4.2 串的存储 4.3 顺序串 4.3.1 算法:基本功能 4.3.2 算法:扩容 4.3.3 算法:求子串 4.3.4 算法:插入 4.3.5 算法:删除 4.3.6 算法:比较 4.4 模式匹配【难点】 4.4.1 概述 4.4.2 Brute-Force算法:分析 4.4.3 Brute-Force算法:算法实现 4.4.4 KMP算法:动态演示 4.4.5 KMP算法:求公共前后缀 next数组 -- 推导 4.4.6 KMP算法:求公共前后缀 next数
陶然同学
2023/02/26
4K0
【数据结构】串与数组
java数据结构之多维数组实现
矩阵中的所有数据通过一定的规律存储在一维数组中。其中k=j*(j-1)/2+i-1。其中j和i是矩阵中的j和i而k是一维数组的下标号。
林老师带你学编程
2022/11/30
4570
数据结构(5):数组
数组是由 n(n≥1)个相同类型的数据元素构成的有限序列,每个数据元素称为一个数组元素,每个元素在 n 个线性关系中的序号称为该元素的下标,下标的取值范围称为数组的维界。
不可言诉的深渊
2021/04/16
1K0
数组和广义表 原
数组是存储同一类型数据的数据结构,使用数组时需要定义数组的大小和存储数据的数据类型。
云飞扬
2019/03/12
7890
数组和广义表
                                                                            原
PHP数据结构(五) ——数组的压缩与转置
PHP数据结构(五)——数组的压缩与转置 (原创内容,转载请注明来源,谢谢) 1、数组可以看作是多个线性表组成的数据结构,二维数组可以有两种存储方式:一种是以行为主序,另一种是以列为主序。 2、当数组存在特殊情况时,为了节省存储空间,可以进行压缩存储,把相同值并有规律分布的元素只分配一个存储空间,对于零元素不进行存储。 有两种情况可以进行压缩存储——特殊矩阵与稀疏矩阵。 3、当数组为特殊的矩阵,例如数组为n阶对称矩阵(满足aij=aji)。对于该类型矩阵,可以只存储一半的数值加上对角线的内容,一共需要分配
用户1327360
2018/03/07
2.4K0
一维数组&二维数组&对称矩阵&三角矩阵&三对角矩阵地址的计算
一维数组的地址计算 设每个元素的大小是size,首元素的地址是a[1],则 a[i] = a[1] + (i-1)*size
lexingsen
2022/02/25
1.9K0
一维数组&二维数组&对称矩阵&三角矩阵&三对角矩阵地址的计算
经典算法之稀疏矩阵
在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。
用户3467126
2019/11/26
4.3K0
经典算法之稀疏矩阵
推荐阅读
【数据结构】数组和字符串(三):特殊矩阵的压缩存储:三角矩阵、对称矩阵——一维数组
2540
【数据结构】数组和字符串(五):特殊矩阵的压缩存储:稀疏矩阵——压缩稀疏行(CSR)
2710
【数据结构】数组和字符串(八):稀疏矩阵的链接存储:十字链表的创建、插入元素、遍历打印(按行、按列、打印矩阵)、销毁
5650
【数据结构】数组和字符串(十):稀疏矩阵的链接存储:十字链表的矩阵操作(加法、乘法、转置)
1690
【数据结构】数组和字符串(四):特殊矩阵的压缩存储:稀疏矩阵——三元组表
1600
数据结构基础(一)数组,矩阵
1.5K0
【数据结构】数组和字符串(七):特殊矩阵的压缩存储:三元组表的转置、加法、乘法操作
1950
文心一言 VS 讯飞星火 VS chatgpt (389)-- 算法导论25.1 2题
960
【数据结构】数组和字符串(九):稀疏矩阵的链接存储:十字链表的插入、查找、删除操作
1150
原 三对角矩阵
1.1K0
盘一盘 Python 特别篇 20 - SciPy 稀疏矩阵
2.1K0
leetcode-766-Toeplitz Matrix(每一条对角线元素的比较)
7550
小白的机器学习实战——向量,矩阵和数组 小白的机器学习实战——向量,矩阵和数组
1.1K0
【数据结构】串与数组
4K0
java数据结构之多维数组实现
4570
数据结构(5):数组
1K0
数组和广义表 原
7890
PHP数据结构(五) ——数组的压缩与转置
2.4K0
一维数组&二维数组&对称矩阵&三角矩阵&三对角矩阵地址的计算
1.9K0
经典算法之稀疏矩阵
4.3K0
相关推荐
【数据结构】数组和字符串(三):特殊矩阵的压缩存储:三角矩阵、对称矩阵——一维数组
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验