自旋锁和互斥锁的区别

序言

  • 最底层的两种锁实现就是互斥锁和自旋锁,许多高级的锁都是基于他们实现的。

  • 加锁的目的是保证共享资源在任意时间内,只有一个线程访问,这样就可以避免多线程导致共享数据错乱的问题。

  • 当有一个线程加锁成功后,其他线程就会加锁失败。

1、互斥锁

互斥锁是一种独占锁,当线程A加锁成功后,此时互斥锁已经被线程A独占了,只要线程A没有释放手中的锁,线程B就会失败,就会释放掉CPU给其他线程,线程B加锁的代码就会被阻塞。

互斥锁加锁失败而阻塞是由操作系统内核实现的,当加锁失败后,内核将线程置为睡眠状态,等到锁被释放后,内核会在合适的时机唤醒线程,当这个线程加锁成功后就可以继续执行。
在这里插入图片描述
互斥锁加锁失败后,会从用户态陷入到内核态,让内核帮助我们切换线程,虽然简化了使用锁的难度,但是存在一定的性能开销成本。

性能开销成本:两次线程上下文切换的成本。
1、当线程加锁失败时,内核将线程的状态从【运行】切换到睡眠状态,然后把CPU切换给其他线程运行;
2、当锁被释放时,之前睡眠状态的线程会变成就绪状态,然后内核就会在合适的时间把CPU切换给该线程运行;

线程切换的上下文?
  当两个线程属于同一个进程,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据。
上下切换的耗时大概在几十纳秒到几微秒之间,如果锁住的代码执行时间比较短,可能上下文切换的时间比锁住的代码执行时间还要长。
若是能确定被锁住的代码执行时间很短,就不应该使用互斥锁,而应该选择自旋锁。

2、自旋锁

  自旋锁通过CPU提供的CAS,在用户态完成加锁和解锁操作,不会主动产生线程上下文切换,所以相比互斥锁来说,会快一些开销小一些。
加锁过程:

  • 查看锁的状态,若是空闲的则执行2
  • 将锁设置为当前线程持有;
    使用自旋锁的时候,当发生多线程竞争锁的情况,加锁失败的线程会忙等待,直到拿到锁。忙等待可以通过while循环实现,不过最好是使用CPU提供的PAUSE指令来实现。

自旋锁利用CPU周期一直自旋直到锁可用。由于一个自选的线程永远不会放弃CPU,因此在单核CPU上,需要抢占式的调度器(不断通过时钟中断一个线程,运行其他线程)。
自旋的时间和被锁住的代码执行的时间成正比关系。

当加锁失败,互斥锁使用线程切换应对,自旋锁用忙等待应对。更高级的锁都会选择其中一个实现

### 自旋锁互斥锁的概念 #### 互斥锁(Mutex) 互斥锁是一种用于保护共享资源不被多个线程同时访问的机制。当一个线程尝试获取已被占用的互斥锁时,该线程会被挂起并进入等待状态,直到持有锁的线程释放锁为止[^2]。 #### 自旋锁(Spin Lock) 自旋锁也是一种同步原语,但是它的行为不同于互斥锁。如果某个线程请求一个已经被占用的自旋锁,则此线程不会立即停止执行而是继续循环检查锁的状态——即“旋转”,直至能够成功取得锁位置[^4]。 ### 自旋锁互斥锁的主要区别 - **阻塞性质** - 对于互斥锁而言,在竞争失败的情况下,进程或线程将会被置于休眠态;对于自旋锁来说,即使未能立刻获得所需资源也会保持活跃状态持续轮询。 - **性能影响** - 使用互斥锁可减少不必要的CPU资源浪费,因为未获准许的操作系统实体处于睡眠模式下并不消耗计算能力。然而这可能导致额外开销如上下文切换等。 - 而采用自旋方式虽然看似简单粗暴却能在某些特定条件下提供更高效的响应速度特别是锁定周期极短的情形之下[^1]。 - **适用环境差异** - 在单核处理器环境中通常推荐优先考虑使用互斥锁来管理并发控制问题。 - 多核心架构下的应用程序里,考虑到跨CPU间的通信延迟等因素,适当运用自旋锁有助于提升整体效率尤其是那些预计占有时间很短暂的关键区域[^3]。 ```cpp // C++代码示例展示如何定义简单的自旋锁类 class SpinLock { private: std::atomic_flag flag = ATOMIC_FLAG_INIT; public: void lock() { while (flag.test_and_set(std::memory_order_acquire)) {} } void unlock() noexcept { flag.clear(std::memory_order_release); } }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值