【锁】悲观锁与乐观锁实现


🏆 前言

锁:在程序中一种保证数据安全的手段和机制。在并发处理共享资源时,可以对共享变量使用syncronized关键字。多用户修改表中同一数据时,可以给该行数据上锁保证数据安全。

在这里插入图片描述


⭐️悲观锁与乐观锁

乐观锁和悲观锁,可以理解为因为一种态度,一种思想定义的一类锁。

  • 乐观锁(Optimistic Lock):像是初出茅庐的书生,对所见事情保持一种乐观的态度。
  • 悲观锁(Pessimistic Lock): 像一个经历社会毒打,对所见保持一种悲观的态度。
  • 在这里插入图片描述

🎯悲观锁 Pessimistic Lock

每次去拿数据的时候都认为别人会修改。所以每次在拿数据的时候都会上锁。这样别人想拿数据就被挡住,直到悲观锁被释放,悲观锁中的共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程
但是在效率方面,处理加锁的机制会产生额外的开销,还有增加产生死锁的机会。另外还会降低并行性,如果已经锁定了一个线程A,其他线程就必须等待该线程A处理完才可以处理
数据库中的行锁,表锁,读锁(共享锁),写锁(排他锁),以及syncronized实现的锁均为悲观锁
————————————————
版权声明:本文为优快云博主「牧小农」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_14996421/article/details/106351873

在这里插入图片描述
如图使用先取锁,再获取数据的方式,保守的保证了数据的安全。

在Mysql中实现悲观锁

两个线程同时去修改id 为1的同一行数据为例,实现悲观锁。
在这里插入图片描述

  • 两个线程对要修改的这一行数据,加悲观锁。
  • 线程#1,如果加锁成功,线程#1可以对数据进行修改;线程#2只能等待线程#1提交或者回滚,释放锁之后。再加锁进行操作。
  • 线程#1,如果加锁失败,说明数据正在被其他线程在处理,只能等待其他线程提交或者回滚。
  1. 首先关闭MySQL数据库的自动提交属性。因为MySQL默认使用autocommit模式,使用SQLset autocommit=0禁用当前session自动提交事务。
  2. 使用SELECT … FOR UPDATE;语法对数据进行加锁操作。
    两个线程(事务)执行结果如下:
  • 线程#1:对数据进行加锁,获取结果
  • 线程#2:一直等待线程#1释放锁,如果线程#1一直不释放锁,线程#2报错,Lock wait timeout exceeded; try restarting transaction
    在这里插入图片描述
    线程#1事务提交之后,线程#2执行结果如下:
    在这里插入图片描述

LockTimeout 超时

在这里插入图片描述
如果事务等待获取排他锁的时间超过LockTimeout ,则将抛出LockTimeoutException ,而不会将该事务标记为已回滚;

死锁处理:悲观锁会增加死锁的可能性,其中两个(或更多)事务各自持有对方想要的锁。当从同一个事务中获得多个悲观锁时,风险会增加;

切记调整死锁超时(数据库检查死锁的超时时间):它的值应该与 LockTimeout 同步!

🎯 乐观锁 Optimistic Lock

每次去拿数据的时候都认为别人不会修改。所以不会上锁,但是如果想要更新数据,则会在更新前检查在读取至更新这段时间别人有没有修改过这个数据。如果修改过,则重新读取,再次尝试更新,循环上述步骤直到更新成功(当然也允许更新失败的线程放弃操作),乐观锁适用于多读的应用类型,这样可以提高吞吐量.
相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本(version)或者是时间戳来实现,不过使用版本记录是最常用的。
————————————————
版权声明:本文为优快云博主「牧小农」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_14996421/article/details/106351873

在这里插入图片描述

在Mysql中实现乐观锁

  • 两个线程对要修改的这一行数据,使用版本号,实现乐观锁
  • 线程#1,对(id=1 and version=0)数据进行修改;版本号+1。
  • 线程#2,对(id=1 and version=0)数据进行修改;更新数据行数为0,说明数据已经被修改,需要重新查询数据进行修改。
    在这里插入图片描述

总结

  • 悲观锁阻塞事务,依赖数据库锁,效率低。更新失败的概率比较低。

  • 乐观锁回滚重试,适用于写比较少的情况,发生冲突也会变小,这样可以省去锁重试的性能开销,加大了系统的整个吞吐量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Abner G

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值