【Linux】自旋锁

一、自旋锁概念

大家都知道互斥锁了,互斥锁呢就是如果这把锁被申请走了,那么该线程就阻塞在这里,直到这把锁被归还回来,那么此时线程拿到这把锁继续执行代码;

而自旋锁呢就是,锁被别的线程申请走了,不阻塞在这里,而是不断的轮询检查该锁是否被归还了;那么这个自旋锁的好处是:如果申请这把锁的线程很快的就把锁归还,那么就可以节约线程切换的开销(如果是阻塞的话:因为阻塞就是线程切换花费是时间还是很多的),但是如果规划的锁的时间非常长,自旋锁不断的轮询访问锁是否被归还,那么是非常浪费CPU资源的;

二、原理

自旋锁通常是使用一个标志位(例如布尔值)来表示该锁是否被占用;如果为 false 表示该锁没有被占用,那么线程就会把这这个布尔值修改成 true ,进入临界资源;如果为 true,表示该锁被其他线程占用了,线程就会循环访问该布尔值是否为 false,直到锁被归还;

伪代码讲解原理:

cpp 复制代码
// 自旋锁的本质:就是一个状态标记
// 0 = 锁是空闲的,可以获取
// 1 = 锁已经被占用
int lock = 0;

// 自旋锁加锁操作
void lock_spin() {
    // 死循环,一直重试(自旋核心)
    while (1) {
        // 原子交换:原子地把 lock 设置成 1,并返回旧值
        // 原子操作 = CPU 保证同一时刻只有一个线程能成功
        if (atomic_swap(&lock, 1) == 0) {
            // 旧值是 0 → 加锁成功!
            break;
        }
        // 加锁失败:不睡眠、不阻塞,立刻循环重试
        // 这就是"自旋":原地循环等待
    }
}

// 自旋锁解锁操作
void unlock_spin() {
    // 直接把标记恢复为 0 即可
    lock = 0;
}

三、优缺点分析

优点:

1)低延迟:自旋锁适用于短时间内的锁竞争情况,因为它不会让线程进入休眠状态,从而避免了线程切换的开销,提高了锁操作的效率。

2)减少系统调度开销:等待锁的线程不会被阻塞,不需要上下文切换,从而减少了系统调度的开销。

缺点:

1)CPU资源浪费:如果锁的持有时间较长,等待获取锁的线程会一直循环等待,导致CPU资源的浪费。

2)可能引起活锁:当多个线程同时自旋等待同一个锁时,如果没有适当的退避策略,可能会导致所有线程都在不断检查锁状态而无法进入临界区,形成活锁。我使用豆包来解析这段话:

注意:退避策略可以是休眠 usleep 1秒

四、使用场景

短暂等待的情况:适用于锁被占用时间很短的场景,如多线程对共享数据进行简单的读写操作。

多线程锁使用:通常用于系统底层,同步多个CPU对共享资源的访问。

注意:在使用自旋锁时,需要确保锁被释放的时间尽可能短,以避免CPU资源的浪费。在多CPU环境下,自旋锁可能不如其他锁机制高效,因为它可能导致线程在不同的CPU上自旋等待。使用豆包来解析这段话:

相关推荐
AIgorithmGEEK4 分钟前
Linux 进程控制完全指南:fork、wait、exec 三部曲
linux·运维·多进程·进程创建·进程等待·进程终止·exec家族
2301_777998348 分钟前
网络基础(一):协议与网络传输基本流程
linux·网络
Lazionr10 分钟前
list容器详解——双向链表的封装与使用
数据结构·c++·链表·list
snow@li10 分钟前
SpringBoot:AOP日志切面全景梳理/原理+流程+实战+避坑
java·开发语言·spring boot
Nil20811 分钟前
C++ emplace_back 与 push_back 详解
开发语言·c++
漂流瓶jz15 分钟前
UVA-12174 Shuffle的播放记录 题解答案代码 算法竞赛入门经典第二版
数据结构·c++·算法·图论·滑动窗口·算法竞赛入门经典·uva
Lysander.Jovian21 分钟前
Nginx服务2
运维·数据库·nginx
小张同学a.23 分钟前
zabbix企业级监控平台4——分布式监控与grafana数据可视化
linux·运维·数据库·分布式·信息可视化·zabbix·grafana
渣渣盟25 分钟前
当 Redis 写入不再是瓶颈后,Flink 任务的反压可能来自哪里?如何系统性地定位和解决 Flink 反压问题?
数据库·redis·flink
七牛开发者27 分钟前
Codex 实践系列 Vol.04:用 Goal 和 Plan 管住一个长任务
java·数据库·人工智能·github·copilot