悲观锁和乐观锁那种效率更高?
3 个回答
慢慢理解世界,慢慢更新自己。java蚂蚁### 简单的总结 一般情况下,乐观锁适合只有读没有写的操作,悲观锁适合于读写混合的操作。如果写操作非常简单短小,比如增加访问人数,也可以用乐观锁,或者在不需要确保读到的数据是最新的时候使用乐观锁。80% 的情况下使用乐观锁确实是比较好的选择。 ### 具体分析 1. **乐观锁** - **适用场景**:主要用于读多写少的场景。通过版本号或时间戳来实现,不会加锁,而是在更新数据时检查是否有冲突。 - **优点**:不会产生锁和死锁问题,高并发情况下效率较高。 - **缺点**:在写操作较多时,可能会导致频繁的冲突检测失败,增加重试次数。 2. **悲观锁** - **适用场景**:适用于读写混合的操作,尤其是写操作较多的场景。通过加锁机制,确保数据一致性。 - **优点**:加锁机制确保数据处理的安全性,在高并发写操作下更加可靠。 - **缺点**:会增加数据库的开销,降低并行性,并且可能会产生死锁。 ### CAS 与高并发 CAS(Compare-And-Swap)依靠硬件 CPU 指令支持去实现原子级操作,所以在高并发的情况下通常更快。它通过自旋来实现,当检测到冲突时不断重试,直至成功。 - **优点**:在读多写少的场景下,CAS 高效且不会产生锁。 - **缺点**:在读写混合场景下,由于频繁的冲突检测,可能会导致 CPU 缓存失效率增加,影响性能。 ### 总结 - **乐观锁**:适用于读多写少的场景,高并发情况下通过自旋实现,效率较高,但在写操作多时可能导致频繁重试。 - **悲观锁**:适用于读写混合的场景,通过加锁机制保证数据一致性,但会增加数据库开销,降低并行性。 总而言之,要提升高并发性能,还是要通过实际测量的数据来说明问题。理论分析只是参考,具体场景下的性能需要通过实践验证。编辑于 2024-05-11 11:55 •IP属地 江苏举报评论收藏
你爱你的玫瑰是因为你在你的玫瑰上花了太多的时间!吴敏悲观锁和乐观锁在不同场景下有不同的适用性,关键问题在于资源竞争的情况是“悲观的”还是“乐观的”。 ### 悲观锁 - **定义**:假定会发生冲突,保护资源不被并发修改。使用时,每次访问数据时都上锁,以保证只有一个线程能够访问数据。 - **特点**:适用于资源竞争激烈的场景。 - **效率**:悲观锁是阻塞操作,不会持续消耗 CPU,但在高并发环境下可能导致线程频繁等待,降低系统吞吐量。 ### 乐观锁 - **定义**:假定不会发生冲突,不加锁而是每次更新时检查是否有冲突。常用的实现方式是 CAS(Compare and Swap)。 - **特点**:适用于资源竞争较少的场景。 - **效率**:乐观锁通过自旋实现,在没有冲突时效率很高,但在高并发环境下,频繁的自旋可能导致大量 CPU 资源被消耗。 ### 选择依据 1. **资源竞争激烈**:如果资源竞争非常激烈,悲观锁可能更合适。乐观锁在这种情况下会让大量请求希望落空,导致频繁自旋,浪费大量 CPU 资源。 2. **资源竞争较少**:如果资源竞争较少,乐观锁通常效率更高。悲观锁在这种情况下意味着不必要地加锁,失去可共享资源的机会。 ### 轻量级锁 vs. 重量级锁 在 Java 虚拟机中,轻量级锁一般情况下优于重量级锁(互斥锁)。但是在高并发、锁竞争激烈的情况下,轻量级锁由于长时间自旋消耗 CPU,可能导致性能比传统的重量级锁更慢。 - **轻量级锁**:使用自旋等待,适用于短时间内可能释放的锁。 - **重量级锁**:使用阻塞等待,适用于长时间持有的锁。 ### 总结 - **悲观锁**:适用于资源竞争激烈的场景。它是阻塞操作,不会持续消耗 CPU,但会导致线程等待。 - **乐观锁**:适用于资源竞争较少的场景。它通过自旋实现,在无冲突时效率高,但高并发下可能会导致大量 CPU 资源消耗。 选择合适的锁策略,需根据具体的业务场景和资源竞争情况来确定。编辑于 2024-01-12 09:35 •IP属地 江西举报评论收藏
鸟随鸾凤飞腾远,人伴贤良品自高。无邪无论是悲观锁还是乐观锁,都是并发控制的一种思想,具体如何选择取决于业务场景。 ### 悲观锁 一般情况下,悲观锁是在数据库层面增加一个排它锁。加锁成功后可以修改数据,然后提交事务,事务提交成功后解锁;如果失败,说明数据正在被修改。如果使用 MySQL 的 InnoDB 引擎,需要注意关闭 MySQL 的自动提交属性 `set autocommit=0`,因为 MySQL 默认使用 autocommit 模式,即执行更新操作后会立即提交。此外,还要注意锁的级别,InnoDB 默认使用行级锁,但如果 SQL 没有使用索引,MySQL 会使用表级锁锁表。 ### 优缺点 - **优点**:悲观锁是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。 - **缺点**:处理加锁的机制会让数据库产生额外的开销,并增加死锁的可能性。在只读型事务处理中没有必要使用锁,会增加系统负载并降低并行性。当某行数据被锁定时,其他事务必须等待该事务处理完才可以处理该行数据。 ### 乐观锁 乐观锁假设数据一般情况下不会造成冲突,因此在提交更新时才进行冲突检测。如果发现冲突,则返回错误信息,让用户决定如何处理。乐观锁一般在代码逻辑层实现,不使用数据库提供的锁机制,通常采用版本号(version)或时间戳来实现。使用版本号时,在数据初始化时指定一个版本号,每次更新操作都对版本号执行+1,并判断当前版本号是否是最新版本号。例如: ```sql 1.查询出商品信息 select status, version from t_goods where id=#{id} 2.根据商品信息生成订单 3.修改商品 status 为 2 update t_goods set status=2, version=version+1 where id=#{id} and version=#{version}; ``` ### 优缺点 - **优点**:乐观锁认为数据竞争的概率较小,因此尽可能直接执行操作,直到提交时才进行锁定,不会产生锁和死锁问题。 - **缺点**:乐观锁存在失效的情况,虽然是小概率事件,但在多个条件共同配合时会出现。例如,应用采用自己的主键 ID 管理策略,读取到某记录后,在该记录被删除和新记录插入后,导致版本号相同的记录覆盖问题。 ### 总结 - **悲观锁**:适用于资源竞争激烈的场景。它是阻塞操作,不会持续消耗 CPU,但会导致线程等待。 - **乐观锁**:适用于资源竞争较少的场景。它通过自旋实现,在无冲突时效率高,但高并发下可能会导致大量 CPU 资源消耗。 选择合适的锁策略,需根据具体的业务场景和资源竞争情况来确定。编辑于 2023-12-07 13:03 •IP属地 辽宁举报评论收藏1
公众号进入网站体验更佳

