面试题:乐观锁和悲观锁
(1)乐观锁和悲观锁概念介绍
介绍乐观锁和悲观锁,可以先理解一下,乐观、悲观两个概念。
-
乐观锁对应于生活中乐观的人总是想着事情往好的方向发展。 悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。
乐观锁和悲观锁是两种思想,不局限在某种编程语言或者数据库。
乐观锁概念
乐观锁在操作数据的时候,非常乐观,都认为别人不会同时修改数据,所以乐观锁在更新数据之前,都不会对数据进行加锁,只有当执行更新数据操作时候,再去判断数据是否被修改,如果数据被修改了,就放弃被当前修改操作。
悲观锁概念
悲观锁在操作数据时候,比较悲观,都认为别人会和自己同时修改数据,所以悲观锁操作数据时候,会直接给数据上锁,不让别人操作,只有自己操作完成后,才释放锁。
(2)乐观锁和悲观锁使用场景
乐观锁使用场景
乐观锁适用于读多写少的情况下,即:读数据多余写数据的时候,可以考虑使用乐观锁。
注意:乐观锁本身是不加锁的,只是会在更新数据时候判断数据是否变化。
悲观锁使用场景
悲观锁适用于写多读少的情况下,即:需要频繁的写数据时候,可以考虑使用悲观锁。
(3)乐观锁和悲观锁实现方式
乐观锁实现方式
-
乐观锁有两种实现方式: CAS机制 版本号机制
《1》CAS机制
CAS有三个操作数:
1) 需要读写的内存位置(V) 2) 进行比较的预期值(A) 3) 拟写入的新值(B)
-
如果内存位置V的值等于预期的A值,则将该位置更新为新值B,否则不进行任何操作。 许多的CAS是自旋的,也就说如果一次不成功,它会一直循环去判断,直到成功为止。
自旋CAS就会占用系统资源,比较耗费CPU的开销。
CAS会导致ABA问题。
ABA问题是指: 线程1修改数据后值等于A,线程2修改数据后值变成B,线程2再次修改数据后值变成A,这样,CAS检查时候,发现修改前后的值是一样的,就认为没有修改,所以CAS操作成功。
《2》版本号机制
版本号机制,是在数据库中添加一个version字段,用于标识哪个版本。每当修改一次数据时候,会将版本号加1。
-
当查询数据时候,将数据中的版本号一起查询出来。 接着修改数据,准备提交更新后的数据到数据库时候,再次查询数据库中版本号。 判断当前查询的版本号是否和第一次查询的一样,如果一样,则进行操作,否则重试。
悲观锁实现方式
-
悲观锁实现,就是通过加锁。 可以对代码块加锁,也可以对数据加锁。 Java中可以使用synchronized同步代码块。 数据库中可以使用排它锁。