【高频】你了解乐观锁和悲观锁吗?

简介: 【高频】你了解乐观锁和悲观锁吗?

一、基本概念

乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。

  • 乐观锁:操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据。如果别人修改了数据则放弃操作,否则执行操作。【在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。】
  • 悲观锁:操作数据时比较悲观,认为别人会同时修改数据。因此修改数据时直接把数据锁住,知道操作完成以后才会释放锁,上锁期间其他人不能修改数据。【传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。】


二、实现方式

悲观锁的实现方式是加锁,加锁既可以是对代码块加锁(synchronized关键字、ReentrantLock),也可以是对数据加锁(MySQL中的排它锁)。

乐观锁的实现方式主要两种:CAS和版本号控制

1.CAS(Compare and Swap:比较再交换),是一个多线程同步的原子指令,CAS包含三个重要信息:内存位置、预期原值、新值。如果内存位置的值和预期的原值相等的话,那么就可以把该位置的值更新为新值,否则不做任何修改。


2.数据版本:即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库增加一个version字段来实现。读取数据时,将此版本号一同读出,之后更新时,对此版本加1.同时将提交数据库的版本数据与数据库表对应的记录的当前版本信息进行对比,若二者相等,则予以更新,否则认为是过期数据。


三、优点缺点

乐观锁(Optimistic Locking)

优点:

1. 不会对数据进行加锁,提升并发性能。

2. 减少了数据库的开销,适合处理读操作多于写操作的场景。

3. 出现冲突时,处理起来较为简单,可以通过版本号等机制进行冲突检测和处理。


缺点:

1. 冲突发生的概率较高,如果频繁出现冲突,可能会影响系统性能。

2. 处理冲突时需要额外的逻辑,开发复杂性增加。

3. 当有大量并发操作时,可能需要多次尝试才能成功完成操作。


悲观锁(Pessimistic Locking)


优点:

1. 在操作数据时会直接对数据进行锁定,避免了数据被其他操作修改的风险。

2. 适合处理写操作多于读操作的场景,可以保证数据的一致性。


缺点:

1. 加锁会降低系统的并发性能,影响系统吞吐量。

2. 容易引发死锁问题,需要谨慎处理。

3. 长时间的锁定可能会阻塞其他操作,造成性能瓶颈。

综合考虑,选择乐观锁还是悲观锁取决于具体的业务场景和需求。在大多数情况下,乐观锁更适合处理高并发场景,而悲观锁适合需要保证数据一致性的场景。


(1) 悲观锁适合用于并发写入多、临界区代码复杂、竞争激烈等场景,这种场景下悲观锁可以避免大量的无用的反复尝试等消耗。


(2) 乐观锁适用于大部分是读取,少部分是修改的场景,也适合虽然读写都很多,但是并发并不激烈的场景。在这些场景下,乐观锁不加锁的特点能让性能大幅提高。


四、灵魂追问

1.乐观锁加锁吗?

答:乐观锁本身不加锁,只是在更新时判断一下数据是否被其他线程更新了;有时乐观锁可能与加锁合作,比如执行update时会加排它锁。但这只是与加锁合作。


2.CAS有哪些缺点?


答:【会出现ABA问题:指的是,线程拿到了最初的预期原值A,然而在将要进行CAS的时候,被其他线程抢占了执行权,把此值从A变成了B,然后其他线程又把此值从B变成A,然而此时的 A 值已经并非原来的 A 值了,但最初的线程并不知道这个情况,在它进行 CAS 的时候,就会误认为它从来没有被修改过,只对比了预期原值为 A 就进行了修改,这就造成了 ABA 的问题。】


  • JDK在1.5时提供了AtomicStampedReference类也可以解决ABA的问题,此类维护了一个“版本号”Stamp,每次在比较时不止比较当前值还比较版本号,这样就解决了 ABA 的问题。
  • 也可以采用CAS的一个变种DCAS来解决这个问题。DCAS,是对于每一个V增加一个引用的表示修改次数的标记符。对于每个V,如果引用修改了一次,这个计数器就加1。然后再这个变量需要update的时候,就同时检查变量的值和计数器的值。


相关文章
|
数据库
什么是数据库悲观锁和乐观锁
什么是数据库悲观锁和乐观锁
328 0
|
3月前
|
缓存 人工智能 安全
别被代码吓跑!产品经理的淘宝API接入避坑指南
本文从产品视角拆解淘宝API对接四步法:①资质认证(执照/通行证);②精准定义数据需求;③防范限流与异常;④严守数据安全底线。帮产品经理摆脱“技术恐惧”,掌握业务边界与规则,高效推动项目落地。
285 0
|
Rust 编译器 C语言
Rust安装手册
卸载 Rust 在任何时候如果您想卸载 Rust,您可以运行 rustup self uninstall。但我们会想念您的!
864 0
Rust安装手册
|
安全 API 网络安全
API安全危机四伏!开发者掌握这“十八般武艺”才能破局?
在数字化时代,API作为连接应用的核心枢纽,其安全性至关重要。本文深入解析API安全攻防实战技巧,涵盖数据传输加密、身份认证、输入验证、速率限制、日志监控、API网关应用及持续安全实践等七大防御策略,帮助开发者全面掌握保护数据接口的关键技能,构筑坚实的安全防线。
791 100
|
9月前
|
弹性计算 Linux 数据中心
阿里云服务器公共镜像、社区镜像、自定义镜像、共享镜像、云市场镜像区别及选择参考
阿里云服务器镜像(也就是云服务器的操作系统)有公共镜像、自定义镜像、共享镜像、云市场镜像、社区镜像可选,对于新手用户来说,不知道他们之间的区别,因此往往不知道如何选择,下面我们来看看他们之间的区别就知道如何选择了。
878 1
|
Java API 数据库
什么是乐观锁,什么是悲观锁?
在互联网公司面试中,很多小伙伴都被问到关于锁的理解。今天,我给小伙伴们来聊一聊我对锁的理解,不管我们互斥锁、自旋锁、重入锁、读写锁、行锁、表锁等等等等这些概念,我把他们都归纳为两种类型,乐观锁和悲观锁。
579 0
|
设计模式 人工智能
AI辅助编程:常用的7种Prompt模式
DevGPT数据集收录了使用ChatGPT进行辅助编程的2万余条提示语及回答;基于该数据集的总结发现了7种常用的提示语模式
662 2
AI辅助编程:常用的7种Prompt模式
|
机器学习/深度学习 人工智能 自然语言处理
抖音封号一般封多久?
根据2023年9月更新的《抖音创作者权益保护指引》,平台将封号时长划分为四级响应机制:
|
Kubernetes 容器 Perl
常用的 Kubernetes(K8S)命令
以上就是一些常用的K8S命令,希望对你有所帮助。在使用这些命令时,记得要根据实际情况进行调整和修改。同时,K8S的命令非常丰富,这里只是列出了一部分,更多的命令和用法,可以通过 `kubectl help`或者查阅K8S的官方文档来了解。
860 18