悲观锁和乐观锁

悲观锁

悲观锁总是假设最坏的情况,每次去拿数据的时候认为别人都会修改数据,所以每次拿数据的时候都会上锁。关系型数据库经常会用到,比如表锁和行锁。
代表就是synchronized和Reentrantlock,经常用于多写场景。

乐观锁

乐观锁总是假设最好的情况,每次去拿数据的时候都认为别人不会更改数据,所以不会上锁。但是在更新的时候会判断一下在此期间别人有没有更改数据。
乐观锁常用于多读场景冲突发生少,省去了锁的开销,提高了整个系统的吞吐量。若是多写场景会发生较多冲突,系统就会不停retry,会降低系统的效率。

乐观锁常见的两种方法:

  • 版本号机制:
    一般在数据表中添加一个版本号version字段,表示数据被修改的次数。当数据被修改时,version值加1。当线程A要更新数据时会读取version值,提交更新时会再次读取version值,若两次读取的version值相同才提交更新,否则会重新读取version执行更新操作。

  • CAS(compare and swap) 比较与交换
    无锁算法。没有线程被阻塞的情况下实现同步,也叫非阻塞同步。
    CAS涉及3个操作数:
    1、需要读写的内存值V
    2、进行比较的值A
    3、拟写入的新值B
    当且仅当V值等于A时,CAS通过原子方式用新值B更新V值。

乐观锁的缺点:

  1. ABA问题。
    如果一个变量V初次读取的时候是A值,再次读取准备赋值的时候仍然是A值。但不能保证没有被其他线程修改过值,因为可能修改又改回A,CAS会误认为它从未被修改过。
    解决方法:
    AtomicStamReference类的compareAndSet方法。
    当前引用是否是预期引用,当前标志是否是预期标志,若全部相等更新值。

  2. 循环开销大
    CAS或版本号一直没有成功,会自旋重试,cpu执行开销非常大。
    解决方法:
    pause指令有一定的提升。
    1、延迟流水线执行命令(de-pipeline)。
    2、可避免在退出循环的时候因内存顺序冲突引起cpu流水线被清空,提高cpu执行效率。

  3. 只能保证一个共享变量的原子操作。
    解决办法:
    AtomicReference类可以将多个变量放在一个对象里进行CAS操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值