学技术学英文:代码中的锁:悲观锁和乐观锁

本文导读:

1. 举例说明加锁的场景:

多线程并发情况下有资源竞争的时候,如果不加锁,会出现数据错误,举例说明:

业务需求:账户余额>取款金额,才能取钱。 

时间线

两人共有账户

Alice取钱

Bob取钱

00:01

余额50

00:02

余额50

查询账户余额50

00:03

余额50

线程中断(cpu暂停执行)

查询账户余额50

00:04

余额20

线程中断(cpu暂停执行)

取30, 50>30, 可以取,执行sql: amount=amount-30

00:05

余额成了-20

取40, 刚才查询的余额为50,所以可以正常取,执行sql:amount=amount-40

这个例子中, 减余额是用sql减的(实际上是数据库服务器执行的减操作),数据库对某一条记录写操作的时候,都会加行锁,防止并发,所以执行sql update实际上是串行的,所以最终金额是-20,数据是对的, 就是不满足业务逻辑:账号余额小于取款金额不能取钱。

这个例子稍作调整,减金额,直接在自己的业务代码里先计算好,然后amount作为参数如传到sql里面直接update,那么最终金额就变成了 10 ,alice 的update会覆盖Bob的update,产生更严重的错误。

这个例子是以数据库为基础的,这样更直观,我们自己的代码也一样,自己设置的全局变量能被多个线程并发访问的时候,也需要做类似的考虑,但一般业务系统都会部署多个实例,所以业务系统中最常用的就是利用其他中间件实现的全局锁。

2. 加锁的两种方式:

悲观锁:提前阻止冲突,就是提前上锁(排他锁、写锁),上锁后独自一个你操作,操作完了其他人再操作,这样就避免并发数据错误。加锁开销高,代价大,适和并发冲突占比高的情况。

乐观锁:容许冲突,先不加锁,真正操作的时候能够检测到冲突,如果检测到了并发冲突,那么就回退重试,检测冲突一般通过版本号实现。适合并发冲突少的情况,只有少量的请求需要回退重试,那么性能就高。

When dealing with conflicts, you have two options:

  • You can try to avoid the conflict, and that's what Pessimistic Locking does.
  • Or, you could allow the conflict to occur, but you need to detect it upon committing your transactions, and that's what Optimistic Locking does.

Now, let's consider the following Lost Update anomaly:

The Lost Update anomaly can happen in the Read Committed isolation level.

In the diagram above we can see that Alice believes she can withdraw 40 from her account but does not realize that Bob has just changed the account balance, and now there are only 20 left in this account.

Pessimistic Locking

Pessimistic locking achieves this goal by taking a shared or read lock on the account so Bob is prevented from changing the account.

In the diagram above, both Alice and Bob will acquire a read lock on the account table row that both users have read. The database acquires these locks on SQL Server when using Repeatable Read or Serializable.

Because both Alice and Bob have read the account with the PK value of 1, neither of them can change it until one user releases the read lock. This is because a write operation requires a write/exclusive lock acquisition, and shared/read locks prevent write/exclusive locks.

Only after Alice has committed her transaction and the read lock was released on the account row, Bob UPDATE will resume and apply the change. Until Alice releases the read lock, Bob's UPDATE blocks.

Optimistic Locking

Optimistic Locking allows the conflict to occur but detects it upon applying Alice's UPDATE as the version has changed.

This time, we have an additional version column. The version column is incremented every time an UPDATE or DELETE is executed, and it is also used in the WHERE clause of the UPDATE and DELETE statements. For this to work, we need to issue the SELECT and read the current version prior to executing the UPDATE or DELETE, as otherwise, we would not know what version value to pass to the WHERE clause or to increment.

Application-level transactions

Relational database systems have emerged in the late 70's early 80's when a client would, typically, connect to a mainframe via a terminal. That's why we still see database systems define terms such as SESSION setting.

Nowadays, over the Internet, we no longer execute reads and writes in the context of the same database transaction, and ACID is no longer sufficient.

For instance, consider the following use case:

Without optimistic locking, there is no way this Lost Update would have been caught even if the database transactions used Serializable. This is because reads and writes are executed in separate HTTP requests, hence on different database transactions.

So, optimistic locking can help you prevent Lost Updates even when using application-level transactions that incorporate the user-think time as well.

Conclusion

Optimistic locking is a very useful technique, and it works just fine even when using less-strict isolation levels, like Read Committed, or when reads and writes are executed in subsequent database transactions.

The downside of optimistic locking is that a rollback will be triggered by the data access framework upon catching an OptimisticLockException, therefore losing all the work we've done previously by the currently executing transaction.

The more contention, the more conflicts, and the greater the chance of aborting transactions. Rollbacks can be costly for the database system as it needs to revert all current pending changes which might involve both table rows and index records.

For this reason, pessimistic locking might be more suitable when conflicts happen frequently, as it reduces the chance of rolling back transactions.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt编译MySQL数据库驱动

目录 Qt编译MySQL数据库驱动 测试程序 Qt编译MySQL数据库驱动 (1)先找到MySQL安装路径以及Qt安装路径 C:\Program Files\MySQL\MySQL Server 8.0 D:\qt\5.12.12 (2)在D:\qt\5.12.12\Src\qtbase\src\plugins\sqldrivers\mysql下…

CTFHUB-web(SSRF)

内网访问 点击进入环境,输入 http://127.0.0.1/flag.php 伪协议读取文件 /?urlfile:///var/www/html/flag.php 右击查看页面源代码 端口扫描 1.根据题目提示我们知道端口号在8000-9000之间,使用bp抓包并进行爆破 POST请求 点击环境,访问flag.php 查看页…

游戏引擎学习第43天

仓库 https://gitee.com/mrxiao_com/2d_game 介绍运动方程 今天我们将更进一步,探索运动方程,了解真实世界中的物理,并调整它们,以创建一种让玩家感觉愉悦的控制体验。这并不是在做一个完美的物理模拟,而是找到最有趣…

YashanDB共享集群产品能力观测:细节足见功底

本文基于前泽塔数科研发总监-王若楠2024年11月在“2024年国产数据库创新生态大会”-“根”技术专场的演讲整理形成,主要对崖山共享集群YAC的架构、功能、高可用性、性能四大方面进行全面测试,并分享了测试环境和测试结论。 年初,基于某些商业…

VMware ubuntu16.04怎么设置静态IP联网

1.将VMware桥接到当前电脑使用的网络上面; 2.点击网络符号,编辑连接; 3.双击有线连接1; 4.选择IPv4设置,将地址,子网掩码,网关,DNS服务器设置好,保存; 5.在终…

ElasticSearch的自动补全功能(拼音分词器、自定义分词器、DSL实现自动补全查询、RestAPI实现自动补全查询)

文章目录 1. 什么是自动补全2. 拼音分词器2.1 初识拼音分词器2.2 下载拼音分词器2.3 安装拼音分词器2.4 测试拼音分词器 3. 自定义分词器3.1 拼音分词器存在的问题3.2 分词器(analyzer)的组成3.3 如何自定义分词器3.4 拼音分词器的可选参数3.5 配置自定义…

Windows环境 (Ubuntu 24.04.1 LTS ) 国内镜像,用apt-get命令安装RabbitMQ,java代码样例

一、环境 Windows11 WSL(Ubuntu 24.04.1) 二、思路 1 用Windows中的Ubuntu安装RabbitMQ,贴近Linux的线上环境; 2 RabbitMQ用erlang语言编写的,先安装erlang的运行环境; 2 用Linux的apt-get命令安装,解决软件依赖…

医学预测模型的网页应用必要模块设计(重制版)

医学预测模型的网页应用必要模块设计(重制版) 刘岳鹏 摘要: 网页应用(Web APP)承载医学临床预测模型并在临床实践中实现与用户的互动,必要的功能模块设计将有助于Web APP更好地在临床实践中发挥其功能。在此…

【他山之石】Leading-Trim: The Future of Digital Typesetting:数字排版的未来 —— Leading-Trim

文章目录 【他山之石】Leading-Trim: The Future of Digital Typesetting:数字排版的未来 —— Leading-TrimHow an emerging CSS standard can fix old problems and raise the bar for web apps1. The problem with text boxes today2. How we got here: a histor…

【k8s集群应用】Kubernetes 容器编排系统

文章目录 Kubernetes 容器编排系统背景与发展Kubernetes 基本概念Kubernetes 集群架构与组件Kubernetes 核心组件Master 组件配置存储中心Node 组件 Kubernetes核心概念1. Pod2. Pod控制器3. Label与Label选择器4. Service5. Ingress6. Volume7. Name与Namespace K8S创建Pod资源…

梳理你的思路(从OOP到架构设计)_简介EIT造形

目录 1、 复习<基类 /子类>的扩充(extends)结构 典型的<基类/子类>代码结构 <基类/子类>代码结构的变形 2、 从<基类/子类>结构到EIT造形 3、 EIT造形的基本形与变形 1、 复习<基类 /子类>的扩充(extends)结构 典型的<基类/子类>代码…

Rust vs C: PNG解码器性能之争的启示

在系统编程领域,C语言一直是性能标杆。但最近一个现象引发了广泛讨论:用 Rust 实现的 PNG 解码器性能竟然超越了 C 语言版本。这个看似反直觉的结果背后,折射出现代编程语言发展的新趋势。 让我们深入解析这个有趣的技术现象。PNG解码本质上是把压缩的图像数据还原成像素数据的…

【收藏】Cesium 限制相机倾斜角(pitch)滑动范围

1.效果 2.思路 在项目开发的时候&#xff0c;有一个需求是限制相机倾斜角&#xff0c;也就是鼠标中键调整视图俯角时&#xff0c;不能过大&#xff0c;一般 pitch 角度范围在 0 至 -90之间&#xff0c;-90刚好为正俯视。 在网上查阅了很多资料&#xff0c;发现并没有一个合适的…

MyBatis-Plus 实用工具:SqlHelper

SqlHelper 是MyBatis-Plus的一款SQL 辅助工具类&#xff0c;提供了一些常用的方法&#xff0c;简便我们的操作&#xff0c;提高开发效率。文档 最常用的是SqlHelper.table(Obj.class) 返回的 TableInfo 对象通常包含以下常用方法&#xff1a; 1. getTableName() 获取表名。示例…

游戏无界,RayLink远程控制电脑打造极致游戏体验

在数字化浪潮席卷全球的今天&#xff0c;电子游戏已经成为我们日常生活中不可或缺的娱乐方式。“游戏无界限”的理念正在逐步改变着玩家们的游戏体验。远程操控电脑技术的兴起&#xff0c;仿佛为游戏世界打开了一扇新的大门&#xff0c;打破了时间和空间的限制&#xff0c;让玩…

【LeetCode】2406、将区间分为最少组数

【LeetCode】2406、将区间分为最少组数 文章目录 一、数据结构-堆、贪心1.1 数据结构-堆、贪心1.2 多语言解法 二、扫描线2.1 扫描线 一、数据结构-堆、贪心 1.1 数据结构-堆、贪心 题目已知一些区间, 需要尽量合并, 使 组 最少. 可以用图解画一下 因为尽量合并, 为了紧凑, …

彻底理解如何优化接口性能

作为后端研发&#xff0c;必须要掌握怎么优化接口的性能或者说是响应时间&#xff0c;这样才能提高系统的系能&#xff0c;本文通过如下两个方面进行分析&#xff1a; 一.后端代码 有如下几步&#xff1a; 1.缓存机制 这是最场景的方式&#xff0c;当使用了缓存后&#xff0c;…

Java性能调优 - JVM性能监测及调优

JVM 内存模型概述 堆 堆是JVM内存中最大的一块内存空间&#xff0c;该内存被所有线程共享&#xff0c;几乎所有对象和数组都被分配到了堆内存中。堆被划分为新生代和老年代&#xff0c;新生代又被进一步划分为Eden和Survivor区&#xff0c;最后Survivor由From Survivor和To Su…

【计算机网络】期末考试预习复习|上

作业讲解 物理层作业 共有4个用户进行CDMA通信。这4个用户的码片序列为&#xff1a; A: (–1 –1 –1 1 1 –1 1 1)&#xff1b;B: (–1 –1 1 –1 1 1 1 –1) C: (–1 1 –1 1 1 1 –1 –1)&#xff1b;D: (–1 1 –1 –1 –1 –1 1 –1) 现收到码片序列&#xff1a;(–1 1 –…

Element plus 下拉框组件选中一个选项后显示的是 value 而不是 label

最近刚进行 Vue3 Element plus 项目实践&#xff0c;在进行表单二次封装的时候&#xff0c;表单元素 select 下拉框组件选中一个选项后显示的是 value 而不是 label&#xff0c;下面上代码&#xff1a; 原来的写法&#xff1a; <el-selectv-if"v.type select"…