前言
乐观锁和悲观锁问题,是出现频率比较高的面试题。本文将由浅入深,逐步介绍它们的基本概念、实现方式(含实列)、适用场景,以及可能遇到的问题面试官追问,希望能帮助你打动面试官。
一、基本概念
乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。
- 乐观锁:乐观锁在操作数据时非常乐观、认为别人不会同时修改数据。因为乐观锁不会上锁,只是在执行更新的时候判断一下再次期间别人是否修改了数据;如果别人修改了数据则放弃操作,否则执行操作。
- 悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,知道操作完成后才会释放;上锁期间其他人不能修改数据。
二、实现方式(含实列)
在说明实现方式之前,需要明确:乐观锁和悲观锁是两种思想,它们的使用时非常广泛的,不局限与某种编程语言或数据库。
悲观锁的实现方式是加锁,加锁既可以对代码块加锁(如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。
原文地址:https://www.cnblogs.com/Edward-Wang/p/10802763.html
时间: 2024-10-08 22:19:13