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

常见锁策略

在多线程编程和分布式系统中,​​锁策略​​是保证数据一致性和系统稳定性的核心机制。不同的场景需要匹配不同的锁策略,本文将系统性地解析常见的锁策略及其适用场景(只解释思想,不涉及实现)。

一、乐观锁 vs 悲观锁

乐观锁(Optimistic Locking)

假设数据一般情况下不会产生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并发冲突进行检测,如果发现并发冲突了,则让返回用户错误的信息,让用户决定如何去做。

​原理​​:假设并发冲突概率低,先操作数据,提交时检测版本(如版本号、时间戳)。

场景​​:读多写少(电商库存更新、文档协作编辑)

​优点​​:减少锁开销,提升吞吐量

​缺点​​:高冲突时频繁重试

悲观锁(Pessimistic Locking)

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。

​原理​​:默认会发生冲突,操作前先加锁(如synchronizedSELECT FOR UPDATE

​场景​​:写操作频繁(银行转账、票务系统)

​优点​​:保证强一致性

​缺点​​:增加线程阻塞风险

二、读写锁(ReadWrite Lock)

多线程之间,数据的读取方之间不会产生线程安全问题,但数据的写入方互相之间以及和读者之间都需要进行互斥。如果两种场景下都用同一个锁,就会产生极大的性能损耗。所以读写锁因此而产生。 读写锁(readers-writer lock),看英文可以顾名思义,在执行加锁操作时需要额外表明读写意图,复数读者之间并不互斥,而写者则要求与任何人互斥。

一个线程对于数据的访问, 主要存在两种操作: 读数据 和 写数据.

  • 两个线程都只是读一个数据, 此时并没有线程安全问题. 直接并发的读取即可.
  • 两个线程都要写一个数据, 有线程安全问题.
  • 一个线程读另外一个线程写, 也有线程安全问题.

核心机制

  • ​读锁共享​​:多个线程可并发读
  • ​写锁独占​​:写操作时禁止其他读写

典型场景

  • 缓存系统(Guava Cache)
  • 配置中心热更新

三、可重入锁(Reentrant Lock)

可重入锁的字面意思是“可以重新进入的锁”,即允许同一个线程多次获取同一把锁。

比如一个递归函数里有加锁操作,递归过程中这个锁会阻塞自己吗?如果不会,那么这个锁就是可重入 锁(因为这个原因可重入锁也叫做递归锁)。

Java里只要以Reentrant开头命名的锁都是可重入锁,而且JDK提供的所有现成的Lock实现类,包括 synchronized关键字锁都是可重入的。

关键特性

  • 线程可重复获取同一把锁
  • 避免死锁(递归调用场景)

实现方式

  • Java的synchronized关键字
  • ReentrantLock

四、公平锁 vs 非公平锁

公平锁: 遵守 "先来后到". B 比 C 先来的. 当 A 释放锁的之后, B 就能先于 C 获取到锁.

非公平锁: 不遵守 "先来后到". B 和 C 都有可能获取到锁.

特性公平锁非公平锁
获取顺序按请求顺序分配允许插队
吞吐量较低(维护队列开销)较高
饥饿风险可能存在

 五、自旋锁(Spin Lock)

工作原理

  • 线程循环检测锁状态(while循环),而非立即阻塞
  • 示例:AtomicBoolean实现
while (!lock.compareAndSet(false, true)) {// 自旋等待
}

如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试会 在极短的时间内到来.

一旦锁被其他线程释放, 就能第一时间获取到锁

适用场景

  • 锁持有时间极短(纳秒级)
  • 内核开发、短任务同步

 六、重量级锁vs轻量级锁

重量级锁

  • ​定义​​:直接依赖操作系统互斥量(Mutex)实现的锁机制
  • ​典型实现​​:Java synchronized关键字(未优化前)、ReentrantLock默认模式
  • ​核心特点​​:线程竞争时会触发​​上下文切换​​,导致线程阻塞

轻量级锁

  • ​定义​​:基于CAS(Compare-And-Swap)等原子操作实现的乐观锁
  • ​典型实现​​:Java偏向锁、自旋锁、AtomicInteger等原子类
  • ​核心特点​​:通过​​忙等待(Busy-Waiting)​​ 避免线程阻塞

核心差异对比

​维度​重量级锁轻量级锁
实现层级操作系统内核态用户空间实现
线程阻塞立即挂起(上下文切换)自旋等待(CPU空转)
响应延迟微秒级纳秒级
内存消耗每个锁关联内核对象(~1KB)仅需存储标记位(~4B)
适用场景高竞争、长临界区低竞争、短临界区
典型CPU消耗低(线程休眠)高(持续自旋)

 

锁策略选择指南

  1. ​冲突概率​​:高冲突选悲观锁,低冲突选乐观锁
  2. ​读写比例​​:读多写少用读写锁
  3. ​响应要求​​:低延迟场景慎用公平锁
  4. ​系统架构​​:分布式环境需CAP权衡

 "没有最好的锁,只有最合适的锁。" —— 分布式系统设计原则

相关文章:

  • 关系型数据库PostgreSQL vs MySQL 深度对比:专业术语+白话解析+实战案例
  • Customizing Materials Management with SAP ERP Operations
  • AI日报 - 2025年04月28日
  • (26)VTK C++开发示例 ---将点坐标写入PLY文件
  • Java多线程实现顺序执行
  • 界面打印和重定向同时实现
  • CodeGeeX 免费的国产AI编程助手
  • HikariCP 6.3.0 完整配置与 Keepalive 优化指南
  • SAP-pp 怎么通过底表的手段查找BOM的全部ECN变更历史
  • 【实战篇】数字化打印——打印格式设计器的功能说明
  • (25)VTK C++开发示例 --- 将点坐标写入.xyz文件
  • 复盘笔记1
  • JavaScript性能优化实战:从瓶颈定位到极致提速
  • UE5 在旋转A的基础上执行旋转B
  • UE5 NDisplay 单主机打包运行
  • Java8 后接口的用法总结
  • Kubernetes/KubeSphere 安装踩坑记:从 context deadline exceeded 到成功部署的完整排障笔记
  • 如何排查服务器中存在的后门程序
  • 纯净IP的优势:稳定性与安全性的结合
  • Spring框架的ObjectProvider用法-笔记
  • 湖南小伙“朱雀玄武敕令”提交申请改名为“朱咸宁”
  • 蜀道考古调查阶段性成果发布,新发现文物遗存297处
  • 上海嘉定远香文化环启用,运动、看展、听歌“一站式解决”
  • 男子称喝中药治肺结节三个月后反变大增多,自贡卫健委回应
  • 中共中央政治局召开会议,分析研究当前经济形势和经济工作,中共中央总书记习近平主持会议
  • 上海未来亚洲研究会第六届会员大会举行,叶青当选会长