【计算机】乐观锁、悲观锁

1.悲观锁

1.1.解释

悲观锁(pessimistic locking)是一种悲观思想,总是假设会发生最坏的情况,本线程的数据很可能会被其他线程所修改,所以悲观锁在持有资源的时候会锁上数据,然后再对数据进行读写,这样其他线程想要请求这个数据的时候就会阻塞,直到等到悲观锁把资源释放为止。

1.2.分类

主要分为共享锁和排他锁。
共享锁(shared locks)又称为读锁,简称S锁。共享锁是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
排他锁(exclusive locks)又称为写锁,简称X锁。排他锁是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据行读取和修改。

1.3.优缺点

悲观锁的优点有:
悲观锁可以完全保证数据的独占性和正确性,适合写操作多的场景。
悲观锁的缺点有:

  • 在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题;
  • 一个线程持有锁后,会导致其他所有抢占此锁的线程挂起;
  • 如果一个优先级高的线程等待一个优先级低的线程释放锁,就会导致线程的优先级倒置,从而引发性能风险。

2.乐观锁

2.1.解释

乐观锁(optimistic locking)对于数据冲突保持一种乐观态度,总认为操作数据不会被其他线程所修改,因而不会对操作的数据进行加锁,只有到数据提交的时候才通过一种机制来验证数据是否存在冲突。
乐观锁并不会真的加锁,而是通过一些状态的检验达到操作互斥的效果。

2.2.实现方式

乐观锁一般有两种实现方式:采用版本号机制 和 CAS算法实现。

2.2.1.版本号机制

版本号机制是在数据表中加上一个 version 字段来实现的,表示数据被修改的次数,当执行写操作并且写入成功后,version = version + 1,当线程A要更新数据时,在读取数据的同时也会读取 version 值,在提交更新时,若刚才读取到的 version 值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。

2.2.2.CAS

CAS(compare and swap),比较与交换算法,一种无锁的算法。即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步。
CAS 中涉及三个要素:

  • 需要读写的内存值 V
  • 旧的预期值 A
  • 拟写入的新值 B

当且仅当预期值A和内存值V相同时,通过原子方式将内存值V修改为B,否则什么都不做。一般情况下是一个自旋操作,即不断的重试。
这个算法有如下缺点:

  • 一个是ABA问题,如果一个变量初次读取的时候是 A 值,它的值被改成了 B,后来又被改回为 A,那 CAS 操作就会误认为它从来没有被改变过。可通过配合版本号机制解决这一问题;
  • 自旋时间长开销大,自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销;
  • CAS 只对单个共享变量有效,当操作涉及跨多个共享变量时 CAS 无效。

2.3.优缺点

乐观锁适合读操作多的场景。

// TODO 可重入锁、不可重入锁
// TODO 公平锁、非公平锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值