乐观锁与悲观锁

  • 悲观锁:每次去拿数据的时候都认为别人会修改。所以每次在拿数据的时候都会上锁。这样别人想拿数据就被挡住,直到悲观锁被释放,悲观锁中的共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程
    • 在对记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。
    • 如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。具体响应方式由开发者根据实际需要决定。
    • 如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。
    • 其间如果有其他事务对该记录做加锁的操作,都要等待当前事务解锁或直接抛出异常。
  • 乐观锁:每次去拿数据的时候都认为别人不会修改。所以不会上锁,但是如果想要更新数据,则会在更新前检查在读取至更新这段时间别人有没有修改过这个数据。一般的实现乐观锁的方式就是记录数据版本(version)或者是时间戳来实现
  • 悲观锁阻塞事务、乐观锁回滚重试
  • CAS:Compare-and-Swap-比较:读取到了一个值 A,在将其更新为 B 之前,检查原值是否仍为 A。如果是,将 A 更新为 B,结束。[1]如果不是,则什么都不做。上面的两步操作是原子性的但是 CAS 有一个问题那就是会产生 ABA 问题
  • ABA:如果一个变量 V 初次读取的时候是 A 值,并且在准备赋值的时候检查到它仍然是 A 值,那我们就能说明它的值没有被其他线程修改过了吗?很明显是不能的,因为在这段时间它的值可能被改为其他值,然后又改回 A
  • 乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去锁的开销
  • 如果经常产生冲突,上层应用会不断的进行重试,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

你可能感兴趣的:(go语言面试,数据库,开发语言)