第七篇: 乐观锁--悲观锁

第七篇: 乐观锁--悲观锁

测试案例

idnamemoney1小明1000

小明的账户上有1000 元 ,现在有两个线程同时往他账户上加钱。

​ 1.A 线程准备往小明的账户上加100, 1, 读取到小明 有 1000 元, 1000 + 100 事务未提交;

​ 2.B 线程准备往小明的账户上加200, 1, 读取到小明 有 1000 元 ,1000 + 200 事务未提交;

​ 3.A 线程提交事务 小明账户余额变成1100, 但这时B 线程还不知道小明账户余额变成1100了;

idnamemoney1小明1100

​ 4.B 线程提交事务 小明账户余额变成1200。

idnamemoney1小明1200

A 线程的更新丢失 本来余额应该是1300,结果余额变成1200

加锁的目的在于保障 一个线程修改数据时这个数据没有被其他线程改过。

一、何为乐观锁与悲观锁

乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。

二、悲观锁

介绍

再事务的基础上,悲观锁 适合短事务(长事务导致其它事务一直被阻塞,影响系统性能),查少该多。

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁,保证了数据安全。(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

使用

悲观锁的概念,他觉有人会修改我读的数据。那我就再查的时候,对数据进行锁定。在数据库中:for update  在Django中:select_for_update()原生sql:1 开启事务2 查询的时候加锁 ---》 select * from user where id =1 for update3 结束事务锁被释放django中:1 开启事务2 在查询的时候 ---》 user.objects.select_for_update().flilter(id=1).first()3 事务结束锁被释放

三、乐观锁

介绍

乐观锁的本质不是,而是一种思想。他是通过代码逻辑来实现锁的。在修改的那一刻判断这个数据有没有被修改。乐观锁适合查多改少。

总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁。但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于多读的应用类型,这样可以提高吞吐量。增加并发量

使用

再事务的基础上:先拿到age数据,在修改的时候再次判断age是否一样。(代码实现)

乐观锁的本质不是锁。他是通过代码逻辑来实现锁的。他觉的别人不会修改的他的数据。他认为读数据不会被别人修改。最后再update时,再where条件中添加,之前查出来的数据。以保证数据的安全性# 方法:先拿到age数据,在修改的时候再次判断age是否一样。(代码实现)1 开启事务2 拆线呢的时候不做任何操作。data = user.objects.flilter(id=1).first()将这个数据中的age在原来的基础上+13 在修在数据的时候。user.objects.filter(id=1,age=data.age).updata(age=data.age+1)从而在我查询到我修改的时候,没有人改动过4 如果3中的影响行数为0,证明数据被人修改。循环再次执行。如果为1,证明数据没人动过,修改成功# 如果是可重复读,上面的乐观锁无效,必须改成read committedsql:之前amount=100,现在修改10UPDATE order_bill set amount = 10 WHERE id = 2810 and amount=100 returning id如果没有id返回,证明在此期间被修改过了,重新执行事物

四、两种锁的使用场景

1.乐观锁 适合查多改少,经常被并发修改的数据可能老是出现版本不一致导致有的线程操作常常失败。2.悲观锁 适合短事务(长事务导致其它事务一直被阻塞,影响系统性能),查少该多。

五、总结

并没有什么乐观锁比 悲观锁好,它们所适应的是不用的场景。你可以根据你的业务选择合适的锁。
免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部