锁的底层原理是什么?

目录

前言

1. 锁的基本概念

2. CAS(Compare-And-Swap)操作

3. Atomic(原子操作)

4. 锁的实现原理

5. 锁的优化技术


前言

锁的底层原理主要依赖于 CAS 操作和原子操作来保证多线程环境下的安全访问。CAS 通过原子性地比较和交换内存值来实现无锁同步,而原子操作则提供了基本的线程安全操作。阻塞锁通过操作系统的线程调度来管理锁的争用,而非阻塞锁通过自旋和 CAS 操作来减少线程挂起的开销。

通过这些底层机制,锁能够有效地解决多线程中的竞争问题,但也要注意锁的选择和使用场景,以平衡性能和开销。

1. 锁的基本概念

锁是一种同步机制,它允许一个线程独占资源的访问权,从而防止其他线程在同一时刻访问该资源。常见的锁类型包括互斥锁(Mutex)、读写锁(Read-Write Lock)和自旋锁(Spinlock)等。

2. CAS(Compare-And-Swap)操作

CAS 是实现锁的一个关键原语,它是一种原子操作,允许线程在不使用锁的情况下实现同步。CAS 操作通常由硬件支持,可以看作是一个伪代码:

bool CAS(atomic<int>* addr, int expected, int new_value) {
    if (*addr == expected) {
        *addr = new_value;
        return true;
    }
    return false;
}
  • 参数解释

    • addr:要操作的内存地址。
    • expected:期望当前内存地址的值。
    • new_value:要更新为的新值。
  • 工作原理

    • CAS 操作会比较内存地址中的值是否与 expected 相等。如果相等,则将其更新为 new_value,并返回 true 表示成功。
    • 如果不相等,则表示其他线程已经修改了该值,操作失败,返回 false

CAS 操作通过一次原子性检查和设置,实现了无锁的同步。它是许多高性能锁和并发数据结构的基础。

3. Atomic(原子操作)

原子操作是另一种底层机制,确保某些操作在 CPU 层面上不可分割。原子操作可以在不使用锁的情况下保证多个线程对共享变量的修改是安全的。

常见的原子操作包括:

  • 原子加减 (atomic_fetch_addatomic_fetch_sub)
  • 原子交换 (atomic_exchange)
  • 原子比较并交换(CAS,atomic_compare_exchange

在 C++ 中,可以通过 std::atomic 提供的原子类型来实现这些操作。

4. 锁的实现原理

锁的实现通常可以分为两大类:阻塞锁非阻塞锁

阻塞锁(Blocking Locks)

阻塞锁,例如互斥锁(Mutex),通过让线程休眠来等待锁的释放。这种实现依赖于操作系统的调度器:

  • 当一个线程尝试获取被占用的锁时,操作系统会将该线程挂起并切换到其他线程,直到锁被释放。
  • 这种方式虽然简单,但线程的挂起和恢复开销较大,适合锁争用较少的场景。

非阻塞锁(Non-blocking Locks)

非阻塞锁,例如自旋锁(Spinlock),通过不断尝试获取锁来避免线程挂起:

  • 当一个线程尝试获取被占用的锁时,它不会立即进入休眠状态,而是不断“自旋”尝试获取锁。
  • 自旋锁通常使用 CAS 操作来实现,当 CAS 操作成功时表示锁已获取,失败则继续自旋。
  • 自旋锁适用于锁的持有时间非常短的场景,否则会导致 CPU 资源浪费。
std::atomic<bool> lock_flag = false;

void lock() {
    while (lock_flag.exchange(true, std::memory_order_acquire)) {
        // 自旋,等待锁释放
    }
}

void unlock() {
    lock_flag.store(false, std::memory_order_release);
}
  • 解释
    • exchange 是一个原子操作,它将 lock_flag 设为 true,并返回先前的值。
    • 如果锁未被持有(lock_flag == false),则当前线程成功获取锁,lock_flag 被设为 true,其他线程继续自旋。
    • unlock 操作将 lock_flag 设为 false,表示释放锁。

5. 锁的优化技术

现代锁的实现会结合多种技术以减少开销和提高性能,例如:

  • 自旋-阻塞混合锁:在短时间内先自旋,超过一定次数后转为阻塞等待。
  • 递归锁:允许同一线程多次获取同一把锁。
  • 无锁数据结构:利用 CAS 实现无锁队列、栈等,避免使用锁。
  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值