当前位置: 首页 > 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权衡

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

http://www.xdnf.cn/news/176959.html

相关文章:

  • 再学GPIO(二)
  • 02 业务流程架构
  • npm、pnpm 和 yarn 包管理工具
  • 【密码学——基础理论与应用】李子臣编著 第八章 SM2公钥密码算法 课后习题
  • LeetCode3☞无重复字符的最长子串
  • 辞九门回忆
  • 深入理解编程中的同步与异步:原理、区别及实战应用
  • Go 语言中的 `select` 语句详解
  • CSS元素动画篇:基于当前位置的变换动画(四)
  • 加密算法 AES、RSA、MD5、SM2 的对比分析与案例(AI)
  • (七)RestAPI 毛子(Http 缓存/乐观锁/Polly/Rate limiting)
  • 【学习笔记1】一站式大语言模型微调框架LLaMA-Factory
  • Vue2 与 Vue3 深度对比与技术解析
  • 黑马点评redis改 part 6
  • 一周学会Pandas2 Python数据处理与分析-Pandas2数据信息查看操作
  • 语音识别质量的跟踪
  • 力扣HOT100之链表:23. 合并 K 个升序链表
  • 树状数组单点操作+前缀K差分->区间K操作 -#131-#132
  • SpringBoot + SSE 实时异步流式推送
  • Linux内核中的编译时安全防护:以网络协议栈控制块校验为例
  • mAh 与 Wh:电量单位的深度解析
  • 【Pandas】pandas DataFrame rtruediv
  • 全网直播推介会,九识智能与申通快递达成全面战略合作
  • 20.压敏电阻的特性与使用注意事项
  • RuoYi-Vue项目Docker镜像构建、推送与部署完整流程
  • 云平台+MQTT+C#上位机+单片机通信
  • 在 UniApp 中实现 App 与 H5 页面的跳转及通信
  • lightrag : from lightrag.utils import EmbeddingFunc 报错
  • 04.通过OpenAPI-Swagger规范让Dify玩转Agent
  • 【Redis】set类型