这是一篇介绍悲观锁和乐观锁的入门文章。旨在让那些不了解悲观锁和乐观锁的小白们弄清楚什么是悲观锁,什么是乐观锁。不同于其他文章,本文会配上相应的图解让大家更容易理解。通过该文,你会学习到如下的知识。
锁(Lock)
在介绍悲观锁和乐观锁之前,让我们看一下什么是锁。
锁,在我们生活中随处可见,我们的门上有锁,我们存钱的保险柜上有锁,是用来保护我们财产安全的。
程序中也有锁,当多个线程修改共享变量时,我们可以给修改操作上锁(syncronized)。
当多个用户修改表中同一数据时,我们可以给该行数据上锁(行锁)。因此,锁其实是在并发下控制多个操作的顺序执行,以此来保证数据安全的变动。
并且,锁是一种保证数据安全的机制和手段,而并不是特定于某项技术的。悲观锁和乐观锁亦是如此。本篇介绍的悲观锁和乐观锁是基于数据库层面的。
悲观锁
悲观锁
(Pessimistic Concurrency Control)
,第一眼看到它,相信每个人都会想到这是一个悲观的锁。没错,它就是一个悲观的锁。
那这个悲观体现在什么地方呢?悲观是我们人类一种消极的情绪,对应到锁的悲观情绪,悲观锁认为被它保护的数据是极其不安全的,每时每刻都有可能变动,一个事务拿到悲观锁后(可以理解为一个用户),其他任何事务都不能对该数据进行修改,只能等待锁被释放才可以执行。
数据库中的行锁,表锁,读锁,写锁,以及syncronized实现的锁均为悲观锁。
这里再介绍一下什么是数据库的表锁和行锁,以免有的同学对后面悲观锁的实现看不明白。
我们经常使用的数据库是mysql,mysql中最常用的引擎是Innodb,Innodb默认使用的是行锁。而行锁是基于索引的,因此要想加上行锁,在加锁时必须命中索引,否则将使用表锁。
3
乐观锁
与悲观相对应,乐观是我们人类一种积极的情绪。乐观锁(Optimistic Concurrency Control)的“乐观情绪”体现在,它认为数据的变动不会太频繁。因此,它允许多个事务同时对数据进行变动。
但是,乐观不代表不负责,那么怎么去负责多个事务顺序对数据进行修改呢?
乐观锁通常是通过在表中增加一个版本(version)或时间戳(times