悲观锁和乐观锁

悲观锁乐观锁”是并发控制领域非常重要的两个核心概念,它们是两种处理多线程共享资源冲突的策略,广泛应用于数据库、操作系统、并发容器、甚至用户态内存管理中。


✅ 简单直观对比

类型思维方式代表手段特点
悲观锁“别人肯定会改,我要先锁!”mutex, synchronized, 数据库锁串行化访问,冲突低性能好
乐观锁“别人可能不会改,我试试看”CAS, 版本号, timestamp高并发高性能,失败需重试

🔒 一、悲观锁(Pessimistic Lock)

💡 原理:

悲观地认为:每次访问共享资源都会发生冲突,所以先加锁再访问,保证线程安全。

🧰 实现手段:

  • C++ 中用 std::mutex, std::lock_guard
  • 操作系统里用 互斥量、读写锁
  • 数据库中用:SELECT FOR UPDATE(阻塞其他事务)

示例(C++):

std::mutex mtx;

void critical_section() {
    std::lock_guard<std::mutex> lock(mtx);  // 自动加锁解锁
    shared_data++;
}

✅ 特点:

  • 简单稳定 ✅
  • 没有冲突也要加锁 ❌(导致性能损耗)
  • 在低并发、高冲突场景中性能较好

😄 二、乐观锁(Optimistic Lock)

💡 原理:

乐观地认为:别人不会同时修改资源,可以先访问,再校验有没有冲突。

如果发现冲突,再重试一次

🧰 实现方式:

  • 使用 版本号时间戳 或原子操作(如 CAS: Compare And Swap)

示例(CAS 写法):

#include <atomic>

std::atomic<int> shared_val = 0;

void try_update() {
    int expected = shared_val;
    int new_val = expected + 1;
    
    // 如果当前值还是 expected,才写入 new_val
    while (!shared_val.compare_exchange_weak(expected, new_val)) {
        expected = shared_val; // 更新预期值,准备下一次 retry
        new_val = expected + 1;
    }
}

✅ 乐观锁特点:

  • 冲突少时性能非常好(几乎无锁)🚀
  • 需要额外机制保证一致性(如版本号、CAS)🔁
  • 并发越高,失败重试越频繁(开销反而大)⚠️

🎯 举个现实比喻:

场景悲观锁乐观锁
厕所上锁锁门才能进 → 一次只进一个人推门进,没人就进,有人就退出重试
打开文档编辑必须申请编辑权限,别人就不能动大家都可以打开,保存时如果冲突就提示你冲突了

🧠 总结对比表:

对比项悲观锁乐观锁
思维模式默认会冲突默认不会冲突
是否加锁是(阻塞)否(非阻塞)
实现方式mutex, rwlockCAS, 版本号,时间戳
性能特点冲突多时稳定冲突少时快,冲突多性能下降
成功概率一般都能成功可能失败需重试
使用场景高冲突区,如数据库写操作高并发低冲突,如计数器、自旋队列

🚀 应用场景举例

场景适合哪种锁原因
数据库事务并发写悲观锁写冲突概率高,稳定性更重要
高性能并发计数器乐观锁并发高,原子操作更轻量
多线程日志输出悲观锁串行化写入,避免数据混乱
并发哈希表(无锁容器)乐观锁CAS 操作 + 重试,无锁更快

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值