lock是悲观锁还是乐观锁_悲观锁和乐观锁

7b50aa63a3d6670fa24a3359a00cf1b5.png

悲观锁也叫悲观并发控制,它通常基于一种假设,即冲突的操作发生的很频繁。因此使用一种阻塞的机制来减少操作的竞争

乐观锁也叫乐观并发控制,它通常基于一种假设,即冲突的操作发生的不是很频繁,在这种情况下的阻塞的机制未免太重量级了,性能上消耗很大,为什么呢?原因如下:

一个线程阻塞时,以前执行该线程的处理器核心会转而执行另一个线程。以前执行的线程的执行状态必须保存到内存中,并加载新线程的状态。这种将核心从运行一个线程切换到运行另一个线程的操作称为 上下文切换
除了直接的上下文切换性能成本,新线程一般会使用来自前一个线程的不同数据。内存访问比处理器时钟慢得多,所以现代系统会在处理器核心与主要内存之间使用多层缓存。尽管比主要内存快得多,但缓存的容量也小得多(一般而言,缓存越快,容量越小),所以任何时刻只能在缓存中保存总内存的小部分。发生线程切换且一个核心开始执行一个新线程时,新线程需要的内存数据可能不在缓存中,所以该核心必须等待该数据从主要内存加载。

因此乐观锁通常会避免阻塞,而采用其他方式来避免冲突

以时间戳为基础的乐观并发控制:这种方式会对每一个对象分配一个时间戳。表示最后访问它的事务,因此每个事务在操作过程当中都需要检查时间戳是否正确,举一个简单的例子,一个事务要对一个证书减10,它会拿到这个数据和它的时间戳,并在本地减10,再取对比时间戳,如果前后一样直接改,并把时间戳更改为当前时间,否则,就重试,因此乐观锁通常伴随着,CAS(比较更改)和自旋(重试),而要向保证该种机制正确性,要保证CAS是原子操作。如java unsafe的compareandswapint。

使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。

而MVCC我觉得和乐观锁不是一回事,多版本并发控制可以结合基于锁的并发控制来解决写-写冲突,即MVCC+2PL,也可以结合乐观并发控制来解决写-写冲突。每种存储引擎实现MVCC的方式是不同的,例如乐观并发控制,悲观并发控制。

MVCC实现Read Committed和Repeatable Read

Read Committed - 一个事务读取数据时总是读这个数据最近一次被commit的版本
Repeatable Read - 一个事务读取数据时总是读取当前事务开始之前最后一次被commit的版本(所以底层实现时需要比较当前事务和数据被commit的版本号)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值