MySQL-锁

DriveCar 2020-04-11

1. 公平锁与非公平锁

公平锁:严格按照线程启动的顺序执行,不允许其他线程插队执行;非公平锁允许插队;

当使用非公平锁时,会立刻尝试配置状态,成功则:插队执行,失败则:与公平锁一样调用acquire()方法,以排他方式获取锁,成功后立刻返回,否则将线程加入队列,直到成功调用为止。

2. 悲观锁与乐观锁

两种常见的资源并发锁设计。

悲观锁:先获取锁,再进行业务操作。悲观:获取锁可能是失败的,因此需要先确保成功地获取到锁再进行业务操作。

  实现:select...for update

  具体:获取select选中的数据行的行锁,当其他并发执行选中同行时会发生排斥,实现锁的效果。当事务结束时会自动释放。

  注意:锁的条数过多时,引起服务大面积等待。

    悲观锁在多线程竞争的条件下,加锁和释放锁会导致比较大的上下文切换和调度延时,引起性能问题;

    优先级高的线程等待优先级低的线程释放锁会导致优先级倒置,引起性能风险;

    其他线程挂起;

  乐观锁:先进行业务操作,再获取锁。乐观:获取锁大概率是成功的,因此在进行完业务操作实际更新数据时再拿锁。

  实现:需要锁的数据上增加版本标识/时间戳

  具体:在业务操作进行前获取需要锁的数据的当前版本号,实际更新数据时确认版本号与之前的相同,并更新版本号。如果更新失败,认为旧数据被并发修改后不存在了,认为获取锁失败,需要回滚整个业务操作并看情况重试。

比较:乐观锁获取锁成功时开销小,但回滚时开销大;适用于取锁失败率小的场景;      

推荐:乐观锁 + 重试  

 

相关推荐