【OS】互斥锁和自旋锁的区别

张开发
2026/4/16 15:59:19 15 分钟阅读

分享文章

【OS】互斥锁和自旋锁的区别
阻塞行为互斥锁加锁失败时线程会进入阻塞状态释放CPU资源由操作系统调度其他线程执行。自旋锁加锁失败时线程会忙等待持续循环检查锁的状态不释放CPU资源。适用场景互斥锁适用于临界区资源访问时间较长或存在阻塞操作的情况如文件I/O、数据库操作等。自旋锁适用于临界区资源访问时间短且线程竞争不激烈的情况如内核态驱动程序开发、轻量级数据结构保护等。临界区资源不是指RTOS的进入临界区那个是需要关中断的性能特点互斥锁在锁竞争激烈时通过让线程睡眠来减少CPU浪费但上下文切换会带来额外开销。自旋锁避免了上下文切换的开销但在高竞争下可能导致CPU资源浪费。底层实现互斥锁内核调度机制等待队列。自旋锁原子操作忙等待。死锁风险互斥锁虽然也存在死锁风险但相对较低因为线程会睡眠其他线程有机会获取锁。自旋锁更容易出现死锁因为不会释放CPU资源如果持有锁的线程进入死循环其他线程将无法获取锁。使用环境互斥锁适用于用户态程序可处理长时间持有锁的情况。自旋锁常用于内核态因为内核中线程不能轻易阻塞。此外在中断处理程序中也只能使用自旋锁用互斥锁的代码可能导致睡眠中断中不能睡眠。补充读写锁基于互斥锁特点是读可以多线程读写只能一个线程写同时读和写是互斥的。读写锁、互斥锁、自旋锁都是悲观锁。悲观锁就好比云文档不能多人同时编辑想要多人同时编辑就要使用乐观锁。乐观锁就是先改共享资源改完再判断有没有别人修改如果发生冲突再说一般用于冲突概率很低的场景比如SVN和Git这种应用。自旋锁的死锁风险进入临界区后不能调用可能引起系统休眠的函数临界区的代码不能被中断函数重入调用如果进入临界区后睡眠会引起这样的问题如下图如果临界区的代码在执行的时候中断重入调用如下图上面两种情况下都出现一个问题就是在临界区运行时还没有来得及释放锁当前进程被动释放了CPU的使用权然后下次「可能是中断处理函数可能是CPU调度的其他线程」再进来的时候情况就会比较复杂因为之前的程序一直没有释放导致锁一直获取失败失败后又一直在等待而且永远等不到锁的释放就会导致死锁了。互斥锁死锁风险A等待BB等待CC等待A互斥锁依赖线程调度在中断中使用互斥锁如果加锁失败就会系统死锁卡在中断里。所以FreeRTOS只提供了在中断条件下的二值信号量函数比如xSemaphoreTakeFromISR不支持阻塞时间。

更多文章