乐观锁是数据库和多线程编程中常用的一种控制并发的方法
乐观锁是数据库和多线程编程中常用的一种控制并发的方法,它的核心思想是“尽可能地让多个事务同时进行,只有在提交前才进行冲突检测”。
下面我为你详细讲解,并用通俗的语言帮助你理解。
一、什么是乐观锁?它的基本思想
乐观锁假设:在大多数情况下,事务之间的冲突(竞争)很少发生,所以在操作数据时不用提前加锁,而是在提交阶段检测是否有冲突。
比喻:想象你在图书馆借一本书,乐观锁就像是你先拿到书进行阅读,不马上告诉管理员,而是在还书时才检测这本书是否已经被别人提前借走。如果有人提前借走,你就得重新等待或者放弃;如果没人借走,你就可以顺利归还。
–
二、乐观锁的工作流程
读取数据(操作前):你读取一份数据(例如银行账户余额)。
进行操作:你在本地或内存中修改数据(比如存款操作)。
提交时检测(写入前):
- 在提交修改之前,系统会检测在这段时间内,数据是否被别人修改过。
- 检测方法常用的有“版本号”或“时间戳”。
冲突检测:
- 如果没有冲突(数据没有被别人改过),就可以把修改提交到数据库,更新数据和版本号。
- 如果检测到冲突(别人已经修改了数据),你可以选择重试(重新读取、操作),或放弃。
三、乐观锁的实现方法
1. 基于版本号的实现
- 在每条数据中加一个版本号(或者时间戳)。
- 操作流程:
- 读取数据时,连同版本号一并读取。
- 更新数据时,带上原有的版本号,执行“条件更新”:
复制代码
UPDATE 表 SET 值=新值, 版本=版本+1 WHERE 条件 AND 版本=原版本号;
- 如果影响行数为0,说明版本号已变(冲突),需要重试。
2. 基于时间戳
- 类似版本号,但用时间戳检查数据是否被修改。
四、乐观锁的优缺点
优点
- 性能好:不需要在操作中锁住数据,减少锁等待时间,适合读取多于写入的场景。
- 适合高并发环境:多个用户同时读写时,不会被锁阻塞。
缺点
- 冲突重试:当冲突发生时,可能需要多次重试,影响效率,尤其是在写入冲突频繁的环境。
- 不保证绝对一致:在高冲突场景下,频繁重试可能导致效率低甚至失控。
五、总结通俗版理解
比喻:假如你和朋友在同时编辑同一份文件(比如共同写一篇文章),乐观锁就像是你们都不用一开始锁住这份文件,只是在最后提交时发现,别人也同时在改。提交前,你会“检查”一下这份文件是否被修改过,如果没有,你就“提交”成功;如果被别人改了,你要么放弃,要么重新开始。
六、实际应用场景举例
- 数据库:购物车、库存管理、银行转账等需要高并发但又低冲突的场景常用乐观锁。
- 分布式系统:比如使用版本号做冲突检测,确保数据一致。
- 业务系统:避免长时间锁住数据,提升性能。