乐观锁和悲观锁简介和实现机制

本文介绍了悲观锁和乐观锁的概念及其在多线程环境中的应用。悲观锁在数据修改前加锁,避免并发问题,但可能导致死锁和降低并发性。乐观锁则在数据提交时检查冲突,适用于高并发场景,但可能存在ABA问题。文章详细讨论了两者的实现机制、优缺点以及如何处理ABA问题和高并发失败的情况。
摘要由CSDN通过智能技术生成

应用场景

为了解决多并发的过程中,对数据的同时操作导致的脏读、换读和不可重复读等问题,提出了悲观锁和乐观锁的概念

悲观锁

  1. 简易概念:在数据修改之前,先给数据加锁,然后再修改数据。其他事务遇到锁,先挂起等待当前线程结束。

  2. 实现机制:数据库本身的锁机制

  3. 分类
    a、共享锁(也叫读锁):多个事务对于同一事务可以共享一把锁,但是都是只能访问读取数据,不能修改数据。
    b、排他锁(也叫写锁):如果一个事务要获取一个数据行的排他锁,那么其他事物就不可以再获取该行的排他锁。但是排他锁可以让事务读取数据和修改数据。

  4. 优缺点:
    优点:不会出现像乐观锁那样的ABA问题
    缺点:悲观锁让数据库产生了额外的开销,有死锁的可能性。此外还降低了并发性,其他事务必须等待当前线程任务结束,才能获取数据。

乐观锁

  1. 简易概念:不认为每个事务都是要读数据进行修改的,所以运行多个事务同时访问数据。但是在数据进行提交的时候,正式对数据的进行检测,检测是否与当前数据冲突等问题。
  2. 实现机制:不依赖数据库本身的锁机制,而是依靠数据本身是否正确,即通过与数据版本比对,从而判断是否可以数据更新。
  3. 优缺点:
    a、优点:减少了事务等待的时间,不会出现死锁的情况
    b、缺点:可能出现ABA的情况

实现过程

悲观锁

实现机制

1、 在对记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。
2、如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。具体响应方式由开发者根据实际需要决定。
3、如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。
4、期间如果有其他对该记录做修改或加排他锁的操作,都会等待我们解锁或直接抛出异常。

使用步骤:

1、关闭MySQL的autocommit模式

set autocommit = 0;

2、SELECT…FOR UPDATE;

select * from student where id = 1 for update;

使用FOR UPDATE需同时满足两个条件

  • 数据库的引擎为 innoDB
  • 操作位于事务块中(BEGIN/COMMIT)
注意事项

使用select…for update会把数据给锁住,不过我们需要注意一些锁的级别,MySQL InnoDB默认行级锁。行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁把整张表锁住,这点需要注意。
常见情况如下:

  • 若明确指明主键,且结果集有数据,行锁;
  • 若明确指明主键,结果集无数据,则无锁;
  • 若无主键,且非主键字段无索引,则表锁;
  • 若使用主键但主键不明确,则使用表锁;

乐观锁

实现机制

CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

缺点问题—ABA问题

ABA问题:线程1从从数据库中取出库存数3,这时候另一个线程2也从数据库中取出库存数3,并且2进行了一些操作变成了2,然后2又将库存数变成3,这时候线程1进行CAS操作发现数据库中仍然是3,然后1操作成功。尽管线程1的CAS操作成功,但是不代表这个过程就是没有问题的。

ABA问题的解决方式

添加版本号,即version字段,每次修改后都将version加一,这样version就是不断增加的,就可以解决ABA问题。

缺点问题—高并发导致失败

乐观锁不像悲观锁,当使用悲观锁的时候,如果当前数据是被锁状态,那么该事务处于挂起状态,等待数据解锁。而乐观锁对数据的访问是不受限制的,只有在提交的那个时刻才会被检查,如果错误就会失败。而在高并发的情况下,如果频繁的报错会降低用户体验。

高并发导致失败的解决方式

减小乐观锁力度,提高吞吐率。

选择:

两种锁各有优缺点,但是在当今网络时代越来越发达的情况下,高并发已经成为常见,那么悲观锁使用就会相对受限制,乐观锁会更长用到。

参考文章

https://www.jianshu.com/p/d2ac26ca6525
https://www.jianshu.com/p/8a70a4af7eac

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值