悲观锁和乐观锁的区别

悲观锁和乐观锁 一、什么是悲观锁,什么是乐观锁 1、锁(Lock)  在介绍悲观锁和乐观锁之前,让我们看一下锁。锁,在我们生活中随处可见,我们的门上有锁,我们存钱的保险柜上有锁,是用来保护我们财产安全的。程序中也有锁,当多个线程修改共享变量时,我们可以给修改操作上锁(syncronized)。当多个用户修改表中同一数据时,我们可以给该行数据上锁(行锁)。  因此,锁其实是在并发下控制多个操作的顺序执行,以此来保证... 阅读详情

这篇文章讲什么

这是一篇介绍悲观锁和乐观锁的入门文章。旨在让那些不了解悲观锁和乐观锁的小白们弄清楚什么是悲观锁,什么是乐观锁。不同于其他文章,本文会配上相应的图解让大家更容易理解。通过该文,你会学习到如下的知识

  1. 什么是悲观锁,什么是乐观锁。

  2. 怎么实现悲观锁,怎么实现乐观锁

  3. 悲观锁和乐观锁的优缺点

  4. 悲观锁和乐观锁的应用场景

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

  1. 锁(Lock):
    在介绍悲观锁和乐观锁之前,让我们看一下锁。锁,在我们生活中随处可见,我们的门上有锁,我们存钱的保险柜上有锁,是用来保护我们财产安全的。程序中也有锁,当多个线程修改共享变量时,我们可以给修改操作上锁(syncronized)。当多个用户修改表中同一数据时,我们可以给该行数据上锁(行锁)。因此,锁其实是在并发下控制多个操作的顺序执行,以此来保证数据安全的变动。 并且,锁是一种保证数据安全的机制和手段,而并不是特定于某项技术的。悲观锁和乐观锁亦是如此。本篇介绍的悲观锁和乐观锁是基于数据库层面的。
    图片描述

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

    这里再介绍一下什么是数据库的表锁和行锁,以免有的同学对后面悲观锁的实现看不明白。
    我们经常使用的数据库是mysql,mysql中最常用的引擎是Innodb,Innodb默认使用的是行锁。而行锁是基于索引的,因此要想加上行锁,在加锁时必须命中索引,否则将使用表锁。

    图片描述

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

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

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

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

idnamenum
1猪肉脯1
2牛肉干1

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

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

    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字段,表变动后的结构如下

    idnamenumversion
    1猪肉脯10
    2牛肉干10

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

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

  1. 悲观锁
    因为悲观锁会影响系统吞吐的性能,所以适合应用在写为居多的场景下。
  2. 乐观锁
    因为乐观锁就是为了避免悲观锁的弊端出现的,所以适合应用在读为居多的场景下。
计算机组成原理(第三版)唐朔飞-第三章系统总线-课后习题 阅读详情

相关推荐

FPGA之道(22)VHDL基本程序框架

在介绍详细的VHDL语法之前,让我们先来了解一下VHDL代码的基本程序框架,这样可以让我们先对VHDL程序设计有一个整体的概念把握,进而在后续的VHDL语法学习中做到有的放矢。

Reborn Lee 8305

乐观锁与悲观锁的区别

乐观锁和悲观锁都是用于解决并发场景下的数据竞争问题,但是却是两种完全不同的思想。它们的使用非常广泛,也不局限于某种编程语言或数据库。 乐观锁的概念: 乐观锁:指的是在操作数据的时候非常乐观,乐观地认为别人不会同时修改数据,因此乐观锁默认是不会上锁的,只有在执行更新的时候才会去判断在此期间别人是否修改了数据,如果别人修改了数据则放弃操作,否则执行操作。 冲突比较少的时候,使用乐观锁(没有悲观锁那样耗时的开销)由于乐观锁的不上锁特性,所以在性能方面要比悲...

qinzuoyu996的博客 5156

智能化运维(AIOps)

• 调查显示,54.79%的企业当前着重关注智能运维的质量领域(包括异常检测、告警收敛、根因分析、 故障处置等)能力建设,其次45.77%的企业关注效率领域,45.49%的企业关注成本领域,30.82%的 企业关注安全领域。从目前的发展情况来看,现阶段AIOps能力大多集中在L2级别, 主要以系统辅助分析,帮助人工进行决策和操作为主,较为领先的 能力实践可以达到L3级别,而L4和L5级别随着AIOps的技术发展 和能力的逐步增强,将是未来智能运维能力建设的发展方向和目标。

追求更专业的设计 3092

乐观锁与悲观锁及应用举例

- 悲观锁:正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)的修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。        以常用的mysql InnoDB存储引擎为例:加入

superli90的专栏 992

遥感目标检测数据集汇总

文章目录1. 光学数据集1.1 DIOR1.2 LEVIR1.3 DOTA1.4 RSOD1.5 NWPU VHR-101.6 VEDAI1.7 COWC1.8 ITCVD1.9 DIUx xView 20181.10 HRSC20161.11 TAS1.12 SZTAKI‐INRIA1.13 UCAS AOD1.14 DLR 3K Vehicle2. SAR2.1 SSDD2.2 SSDD+2....

quanwei的博客 6万+

tkinter动态表格 - 实时更新数据(TkinterTable)

tkinter动态表格 - 实时更新数据(TkinterTable) 参考 [TkinterTable] Tkinter上的表格GUI】 https://github.com/dmnfarrell/tkintertable/wiki/Usage https://github.com/dmnfarrell/tkintertable/issues/47 python使用tkinter编写一个数据显示窗口(实时显示更新的数据) 首先安装TkinterTable,即pip install tki

qq_33934427的博客 1万+

乐观锁与悲观锁的根本区别,以及使用场景分析

乐观锁与悲观锁的根本区别,以及使用场景分析

kerwin的博客 2万+

使用 Simulink + Simscape Electrical 搭建一个三相PWM整流器模型

本文详细介绍了使用Simulink搭建三相PWM整流器模型的方法,重点讲解了SVPWM调制策略的实现过程。内容包括系统结构设计、主电路搭建、SVPWM算法实现、双闭环控制器设计以及仿真分析。通过MATLAB Function Block实现SVPWM核心算法,并给出优化建议,如死区补偿、开关频率优化等。该教程为电力电子领域工程师提供了实用的建模与仿真方法,可用于新能源并网、电机驱动等应用场景的研发与优化。

amy_mhd的博客 195

数据库乐观锁,悲观锁的区别,怎么实现

【面试干货】数据库乐观锁,悲观锁的区别,怎么实现

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 6888

《Linux GPU 驱动核心机制:面向图形与 AI 计算的 DRM 内存管理与任务调度》 目录

本文以缓冲区对象(BO)生命周期为主线,系统解析 Linux DRM 子系统中 GPU 驱动的核心机制。涵盖 GEM 与 TTM 内存管理、dma-buf/dma-fence 共享同步、GPU 调度与地址空间管理,结合 amdgpu、Xe 等驱动代码,深入剖析其设计动机与实现逻辑。旨在填补中文领域对 GPU 内核机制系统性讲解的空白,为图形与 AI 计算场景下的内存泄漏、同步死锁等疑难问题提供可追溯的分析路径。

图形/计算GPU的驱动与虚拟化技术分享园地 3709

【00】虹软2023届校招专场 ,计算机类笔试攻略(笔试考试时间、考察范围、笔试难度 等说明)

虹软科技2023校招笔试攻略:三大岗位类别(算法、算法优化、开发)分别于7月24日进行。题型包括选择题、编程题和问答题,其中算法类题目降低难度,编程题改为LeetCode模式。重点考察数学基础、机器学习、编程能力(C/C++/Python)、数据结构和算法优化等。建议根据投递岗位选择问答题,算法优化类注重系统知识和SIMD优化,开发类侧重多线程等实际应用能力。笔试结果将作为校招offer的重要参考。

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 276

乐观锁与悲观锁的区别与实际应用

悲观锁的基本思想是:每次访问共享资源时,都假设其他线程会对资源进行修改,因此需要加锁来保证对资源的独占访问。简言之,悲观锁在访问资源时,认为数据可能会被其他线程修改,所以“悲观”地对资源进行加锁,防止其他线程访问。数据库的行级锁(SQL中的锁)操作系统中的互斥锁(Mutex)Java中的关键字和在多线程编程和分布式系统中,乐观锁和悲观锁是两种常见的并发控制策略。悲观锁适用于资源竞争激烈、数据冲突频繁的场景,而乐观锁适用于资源竞争较轻、冲突较少的情况。

一碗黄焖鸡三碗米饭的博客 1598

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Java中悲观锁和乐观锁的区别

Java中悲观锁和乐观锁的区别

2301_77899321的博客 909

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

MySQL悲观锁和乐观锁有什么区别?

顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁。正因为如此,悲观锁需要耗费较多的时间,另外与乐观锁相对应的,悲观锁是由数据库自己实现了的,要用的时候,我们直接调用数据库的相关语句就可以了。说到这里,由悲观锁涉及到的另外两个锁概念就出来了,它们就是共享锁与排它锁。共享锁和排它锁是悲观锁的不同的实现,它俩都属于悲观锁的范畴。乐观锁是用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。

学亮编程手记 588

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

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

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

天天的博客 933

synchronized和lock的区别;悲观锁和乐观锁的区别

synchronized和lock的区别:  1.用法不一样。synchronized既可以加在方法上,也可以加载特定的代码块上,括号中表示需要锁的对象。而Lock需要显示地指定起始位置和终止位置。synchronzied是托管给jvm执行的,Lock锁定是通过代码实现的。  2.在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock...

毕富国的博客 9120

悲观锁与乐观锁:怎么区别引用它们?

悲观锁(Pessimistic Lock)是一种假设冲突会频繁发生的锁机制。在每次数据访问时,它会先加锁,直到操作完成后才释放锁。这确保了在锁持有期间,其他线程无法访问这段数据,从而避免了并发冲突。乐观锁(Optimistic Lock)是一种假设冲突不会频繁发生的锁机制。在每次数据访问时,它不加锁,而是在更新数据时检查是否有其他线程修改过数据。如果检测到冲突,则重试操作或抛出异常。特征悲观锁乐观锁假设前提假设冲突会频繁发生,需要加锁保护假设冲突不会频繁发生,通过版本号检测性能。

流楚丶格念的博客 593

彻底理解乐观锁和悲观锁的区别

乐观锁 在关系数据库管理系统里,乐观并发控制(又名”乐观锁”,Optimistic Concurrency Control,缩写”OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的 那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回 滚。乐观事务控制最早是由孔祥重(H.T.Kung)教授提出。 乐观并发控制的阶段 乐观并发控制的事务包

专注自动化、性能测试、测试架构学习交流 1494

数据库 并发 悲观锁 乐观锁 是什么 区别

一、并发控制 当程序中可能出现并发的情况时,就需要保证在并发情况下数据的准确性,以此确保当前用户和其他用户一起操作时,所得到的结果和他单独操作时的结果是一样的。这种手段就叫做并发控制。 没有做好并发控制,就可能导致脏读、幻读和不可重复读等问题。 常说的并发控制,一般都和数据库管理系统(DBMS)有关。 在 DBMS 中的并发控制的任务,是确保在多个事务同时存取数据库中同一数据时,不破坏事务的隔离性、一致性和数据库的统一性。 实现并发控制的主要手段大致可以分为乐观并发控制和悲观并发控制.

软件工程小施同学 的专栏 1516

乐观锁和悲观锁的区别

悲观锁和乐观锁是在并发编程中常见的两种锁机制,它们分别基于不同的假设和实现方式来处理共享资源的访问和修改。

m0_66216860的博客 1256

悲观锁和乐观锁的区别和使用

悲观锁和乐观锁的区别和使用

相关项目可以查看https://gitee.com/fan-pl或https://github.com/fpl1116 615
上一篇: java.lang.ClassNotFoundException:org.elasticsearch.action.count.CountRequestBuilder
下一篇: SpringBoot和SpringCloud之间的关系
@百思不如奇解
博客等级 码龄5年 352粉丝 101原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@百思不如奇解

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值