【数据库】--- 悲观锁和乐观锁(面试考点) - Go语言中文社区

【数据库】--- 悲观锁和乐观锁(面试考点)


一、乐观锁

1.什么是乐观锁?

总是认为不会产生并发的问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般使用版本号机制或CAS机制来实现!
在这里插入图片描述

2.CAS机制

CAS是乐观锁的一种实现方式,是一种轻量级的锁!

原理线程在读取数据时不进行加锁,在准备写回数据时,先去查询原值,操作的时候比较原值是否被修改,若为被修改则写回,否则,重回新执行读取流程。
在这里插入图片描述

3.乐观锁带来的问题

因为CAS操作长时间不成功的话,会导致一直自旋,相当于死循环,造成CPU消耗过大!

二、悲观锁

1.什么是悲观锁?

总是假设最坏情况,每次取数据时都认为其他线程会修改数据,所以都会加锁,当其他线程想要访问数据时,都要挂起等待。
在这里插入图片描述

2. synchronized机制

synchronized,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行

  • synchronized 对对象进行加锁,在 JVM中,对象在内存中分为三块区域:对象头(Header)、实例数据(InstanceData)和对齐填充(Padding)。
  • 对象头:我们以Hotspot虚拟机为例,Hotspot的对象头主要包括两部分数据:Mark Word(标记字段)、Klass Pointer(类型指针)。

你可以看到在对象头中保存了锁标志位和指向 monitor 对象的起始地址,如下图所示,右侧就是对象对应的 Monitor 对象。
在这里插入图片描述
当 Monitor 被某个线程持有后,就会处于锁定状态,如图中的 Owner 部分,会指向持有 Monitor 对象的线程。

另外 Monitor 中还有两个队列分别是EntryList和WaitList,主要是用来存放进入及等待获取锁的线程。

如果线程进入,则得到当前对象锁,那么别的线程在该类所有对象上的任何操作都不能进行。

  • Mark Word:默认存储对象的HashCode,分代年龄和锁标志位信息。它会根据对象的状态复用自己的存储空间,也就是说在运行期间Mark
    Word里存储的数据会随着锁标志位的变化而变化。
  • Klass Point:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

三、乐观锁和悲观锁的适用场景

1.响应速度:如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁

2.冲突频率:如果冲突频率非常高,建议采用悲观锁,保证成功率,如果冲突频率大,乐观锁会需要多次重试才能成功,代价比较大

3.重试代价:如果重试代价大,建议采用悲观锁

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/L19002S/article/details/108034851
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢