面试官:你了解乐观锁和悲观锁吗?

前言

  乐观锁和悲观锁问题,是出现频率比较高的面试题。本文将由浅入深,逐步介绍它们的基本概念、实现方式(含实列)、适用场景,以及可能遇到的问题面试官追问,希望能帮助你打动面试官。 

一、基本概念

  乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。

  • 乐观锁:乐观锁在操作数据时非常乐观、认为别人不会同时修改数据。因为乐观锁不会上锁,只是在执行更新的时候判断一下再次期间别人是否修改了数据;如果别人修改了数据则放弃操作,否则执行操作。
  • 悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,知道操作完成后才会释放;上锁期间其他人不能修改数据。

二、实现方式(含实列)

  在说明实现方式之前,需要明确:乐观锁和悲观锁是两种思想,它们的使用时非常广泛的,不局限与某种编程语言或数据库。

  悲观锁的实现方式是加锁,加锁既可以对代码块加锁(如java的synchronized关键字),也可以是对数据加锁(如MySQL中的排它锁)。

  乐观锁的实现方式主要有两种:CAS机制版本号机制。下面详细介绍。

  1、CAS(Compare And Swap)

  CAS操作包含了3个操作数:

  • 需要读写的内存位置(V)
  • 进行比较的预期值(A)
  • 拟写入的新值(B)

  CAS操作逻辑如下:如果内存位置V的值等于预期的A值,则将该位置更新为新值B,否则不进行任何操作。许多CAS的操作时自旋的;如果操作不成功,会一直重试,直到操作成功为止。

  这里引出一个新的问题,既然CAS包含了Compare和Swap两个操作,它由如何保证原子性呢?答案是:CAS是由CPU支持的原子性,其原子性在硬件层面是保证的。

  下面以Java中的自增操作(i++)为例,看一下悲观锁和CAS分别是如何保证线程安全的。我们知道,在Java找那个自增操作不是原子操作,它实际上包含三个独立的操作:①、读取 i 值,②、加 1,③、将新值写回 i。

  

猜你喜欢

转载自www.cnblogs.com/Edward-Wang/p/10802763.html