当前位置: 首页 > news >正文

悲观锁和乐观锁

在多线程编程中,乐观锁悲观锁是两种解决并发安全问题的核心策略,它们的核心策略在于对“数据竞争风险”的假设和应对方式。

核心思想与定义

1. 悲观锁

  • 核心思想:“悲观”地假设冲突很可能发生。在操作数据(尤其是修改)之前,预先锁定该数据,确保在持有锁的期间,其他事务无法修改(甚至有时无法读取)该数据,从而避免冲突。
  • 行为模式:“先取锁,再操作”。事务开始时或操作数据前就获取锁(如行锁、表锁),直到事务提交或回滚才释放。

2. 乐观锁

  • 核心思想:“乐观”地假设冲突很少发生。允许事务在不加锁的情况下直接读取和修改数据。但是在提交修改之前,会检查此期间的数据是否被其他事务修改过。如果检测到冲突,则放弃本次修改(通常通过回滚或重试机制处理)。
  • 行为模式:“先操作,提交时再检查冲突”。核心在于冲突检测而非冲突避免。

实现机制

1. 悲观锁实现(通常由数据库直接提供)

  • 数据库锁机制:直接利用数据库的锁功能。
    • 行级锁:SELECT ... FOR UPDATE (加排他锁/X锁), SELECT ... LOCK IN SHARE MODE (加共享锁/S锁 - 较少用于悲观更新)。这是 InnoDB 等支持行锁引擎的标准做法。FOR UPDATE 会阻塞其他事务的 FOR UPDATE 和普通写操作。
    • 表级锁:LOCK TABLES ... WRITE/READ。粒度大,并发性低,在支持行锁的引擎中不推荐用于细粒度并发控制。
  • 特点:
    • 强一致性:锁定期间保证数据的绝对独占性。
    • 阻塞:获取不到锁的事务会阻塞等待,直到锁释放或超时。
    • 开销:加锁、解锁、维护锁、处理死锁都需要开销。
    • 死锁风险:多个事务循环等待对方持有的锁会导致死锁,需要数据库死锁检测和回滚。

2. 乐观锁实现(通常需要应用层逻辑配合数据库特性)

  • 核心:版本控制
    • 数据表增加版本字段:如 version (整数) 或 timestamp (时间戳)。
    • 读取:读取数据时,同时记录当前版本号 V_old
    • 修改:更新数据时,在 WHERE 条件中包含主键读取时的版本号 V_old,并将版本号 +1 (或更新时间戳)。
  • 冲突检测:
    • ​​​​​​​如果 UPDATE 语句返回的“影响行数”为 0,说明在读取之后、提交之前,该行数据已经被其他事务修改(V_old 与当前数据库中的版本号不匹配),即发生了冲突。
    • 应用层检测到影响行数为 0 后,需要根据业务逻辑处理冲突(典型处理:回滚当前事务、重试整个业务操作、提示用户等)。
  • 特点:
    • ​​​​​​​非阻塞:读操作不加锁,写操作只在提交瞬间进行版本检查(本质是一个原子操作),不会导致其他事务阻塞等待(但冲突的事务需要自己处理失败)。
    • 高并发:冲突率低的场景下,性能通常优于悲观锁(省去了加锁开销和等待时间)。
http://www.lqws.cn/news/190189.html

相关文章:

  • 命令行以TLS/SSL显式加密方式访问FTP服务器
  • 【Linux】ps 命令详解及使用示例:查看当前运行进程状态
  • Linux配置yum 时间同步服务 关闭防火墙 关闭ESlinux
  • 《C语言·源初法典》---C语言基础(上)
  • python fbx sdk
  • C/C++ 中附加包含目录、附加库目录与附加依赖项详解
  • placeholder不显示and模板字符串无效
  • leetcode sql50题
  • clickhouse 学习总结
  • Charles 全流程指南:安装、设置、抓包与注意事项
  • Redis知识
  • 缓解骨质疏松 —— 补钙和补维 D
  • LangChain【8】之工具包深度解析:从基础使用到高级实践
  • C++.OpenGL (6/64)坐标系统(Coordinate Systems)
  • C++单例模式教学指南
  • 2003-2024年高铁列车信息数据
  • PP-OCRv5_server_det.yml参数解释
  • 【PDF PicKiller】PDF批量删除固定位置图片工具,默认解密,可去一般图、背景图、水印图!
  • 图片切割工具:智能分割长图并控制文件大小
  • 谷歌云代理商 | 游戏行业专属方案:谷歌云实时多人游戏服务器架构
  • 使用 Docker Compose 从零部署 TeamCity + PostgreSQL(详细新手教程)
  • 35.成功解决编写关于“江协科技”编写技巧第二期标志位积累的问题
  • vue3学习(toRefs和toRef,computed计算属性 ,v-model指令,箭头函数)
  • 【leetcode】3. 无重复字符的最长子串
  • 跟我学c++中级篇——理解类型推导和C++不同版本的支持
  • 如何在Lyra中创建一个新的Game Feature Plugin和Experience游戏体验
  • 前端flex、grid布局
  • idea中 maven 本地仓库有jar包,但还是找不到,解决打包失败和无法引用的问题
  • AC68U刷梅林384/386版本后不能 降级回380,升降级解决办法
  • day35-系统编程之网络编程IV及MQTT协议