• 悲观锁与乐观锁介绍,优缺点


    什么是锁,为什么需要锁

            在Java中,锁是一种同步机制,用于控制多个线程对共享资源的访问。共享资源可以是变量、方法或对象。当多个线程同时尝试访问共享资源时,可能会发生竞争条件,导致不可预测的行为。

    数据错误例子

    假设有一个简单的股票交易系统,其中两个线程分别代表买家和卖家。买家线程和卖家线程同时尝试购买和卖出股票,但是没有使用锁来保护共享资源。

    1. 买家线程和卖家线程同时检查库存,结果都发现还有股票可供购买或出售。于是,两个线程同时减少库存,导致库存数量减少两次,从而导致数据错误。
    2. 买家线程和卖家线程同时尝试增加库存,但由于买方和卖方都在尝试增加同一个变量(stockCount)的值,可能导致该变量的值不正确。
    3. 买家线程和卖家线程同时增加买家和卖家的股票数量,可能导致两个线程增加的数量不正确,从而导致数据错误。

            为了确保对共享资源的访问不会发生冲突,需要使用锁来保证同一时刻只有一个线程能够访问共享资源

    悲观锁和乐观锁都是一种锁优化策略,用于减少锁的使用和锁竞争,从而提高并发性能。

    什么是悲观锁

            当多个线程同时尝试获取同一个锁时,悲观锁策略会假设最坏的情况,即假定多个线程同时获取锁会导致数据不一致。因此,它会采取一种较为保守的策略,避免多个线程同时获取锁。

    对数据采取“悲观”态度,认为数据随时都有可能被别人改。

    读取的时候就开始霸占,别人想改得排队,等我改完再说。

    优点:

    1. 有序队列

    2. 无重试开销

    3. 业务开发无需复杂的适配逻辑,符合线性开发思维

    缺点:

    1. 产生饥饿:在某些情况下,悲观锁可能会导致饥饿现象,即某些线程长时间得不到锁,而其他线程却可以随时获得锁。这可能会导致某些线程长时间处于阻塞状态,从而影响程序的性能。
    2. 资源占用:悲观锁在等待锁的过程中会占用CPU资源,从而可能导致CPU资源占用过高。
    3. 死锁:在某些情况下,悲观锁可能会导致死锁现象,即多个线程相互等待对方释放锁,从而导致程序无法继续执行。

    什么是乐观锁

            乐观锁的核心思想是在获取锁之前先进行尝试性读取共享资源,如果读取成功,则认为没有其他线程同时访问该资源,可以获取锁并进行写入操作。如果读取失败,则说明有其他线程同时访问该资源,需要重新进行读取并尝试获取锁。

    对数据采取“乐观”态度,认为我在修改数据的同时,数据大概率不会被别人动过。

    读数据不独占,而是保存修改的时候再检查一下是否变更(同时),如果被改过了,就重读重做。

    优点:

    1. 无堵塞风险

    2. 业务不排队,高效率优先

    3. 最大化整体效率

    缺点:

    1. 代码复杂性:在使用乐观锁时,需要考虑重试策略、超时等问题,这可能会导致代码复杂性增加,维护成本提高。
    2. 如果发生了频繁的业务间修改冲突,就会引发频繁重复的重试,造成计算资源的浪费。
    3. 并发读操作:在乐观锁中,读取操作不需要加锁,因此可能会有多个线程同时进行读取操作,这可能会导致读取结果不一致。

    悲观锁与乐观锁哪个更好

    各业务之间处理时间相近:悲观锁

    各业务之间处理时间差异大:乐观锁

    并非绝对,根据具体情况调整

  • 相关阅读:
    POI2020题解
    观影《铁拳男人》有感
    Redis Key操作
    状压dp和状态机dp题目汇总(持续更新)
    【MySQL查缺补漏学习】六、MySQL中使用JOIN小结
    怎么制作精美的公众号文章?教你几招
    设计模式:命令模式
    Spring-IOC
    vue实战——路由访问权限【详解】
    【踩坑】Putty报错: Can’t agree a key change algorithm
  • 原文地址:https://blog.csdn.net/Pretty_TokaiTeio/article/details/138199058