自旋锁

1,567 阅读2分钟

自旋锁概念

自旋锁应该是Linux内核中使用最多的锁了,其它锁很多都依赖自旋锁实现。自旋锁概念上简单,一个自旋锁是一个互斥设备,只能有2个值:"上锁"和"解锁"。它常常实现为一个整数值中的一个单个位,想获取一个特殊锁的代码测试相关的位,如果锁是可用的,这个"上锁"位被置位并且代码继续进入临界区;相反,如果这个锁已经被别人获得,代码进入一个紧凑的循环中反复检查这个锁,直到它变为可用。这个循环就是自旋锁的"自旋"部分。

选择自旋锁,自旋等待的代价应该要尽可能的小于线程调度的代价。即,使用自旋锁的一个重要规则是自旋锁必须一直是尽可能短时间的持有。这个很好理解,因为你持有的时间越长,其他线程就不得不长时间自旋等待。同时持有线程不应被抢占或睡眠,如果真发生了,其他等待线程就悲剧了。

自旋锁API

相关API,头文件#include<linux/spinlock.h>

void spin_lock_init(spinlock_t *lock);  //初始化
void spin_lock(spinlock_t *lock);       //加锁
void spin_unlock(spinlock_t *lock);     //释放锁

// ...... 其他API这里不再列出 ......
  • spin_lock_init——对应的逻辑可以理解为对标识位初始化;
  • spin_lock——对应的逻辑可以理解为,先尝试加锁(对标识位进行操作),如果成功则可持有临界资源,如果尝试加锁失败,就进入do-while循环继续尝试加锁(即,自旋),直到加锁成功;
  • spin_unlock——对应的逻辑是将标识位置为未加锁状态;

Linux版本不同,对应的实现可能是不同的,Linux-2.6.25版本后实现了先到先得功能,所以实现的代码与之前版本是不同的,大致思路是相同的,只是标识位及判断状态的方法不同。

参考文档:
带您进入内核开发的大门 | 自旋锁的使用
自旋锁