栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux自旋锁

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux自旋锁

Linux自旋锁
  • 原子操作
  • 自旋锁
        • 存在问题
        • 解决方案
  • CAS 函数
  • PAUSE 指令
  • 自旋锁原理
  • 自旋锁相关API
        • 定义自旋锁
        • 初始化自旋锁
        • 获取自旋锁函数
        • 尝试获取自旋锁函数
        • 释放自旋锁

原子操作
  • 简单易用
  • 只能作计数操作,保护的东西太少
自旋锁

主要用于多核处理器

  • 短时期的轻量级加锁

  • 加锁失败时,原地打转、忙等待

  • 避免上下文调度、系统开销较小

加锁步骤:

  1. 查看锁的状态,如果锁是空闲的
  2. 将锁设置为当前线程持有
存在问题

在没有 CAS 函数前,多个线程同时执行这 2 个步骤是会出错的。

解决方案

CAS 函数把这 2 个步骤合并为一条硬件级指令。这样第 1 步比较锁状态和第 2 步锁变量赋值,将变为不可分割的原子指令(硬件同步原语)

CAS 函数

自旋锁使用CPU 提供的 CAS 函数(Compare And Swap),在用户态代码中完成加锁与解锁操作

PAUSE 指令

自旋锁并不一直"忙等待",会与 CPU紧密配合 ,它通过 CPU 提供的 PAUSE 指令,减少循环等待时的耗电量;对于单核CPU,忙等待并没有意义,此时它会主动把线程休眠。

自旋锁原理
  • 设自旋锁为变量 lock,整数 0 表示锁是空闲状态,整数 pid 表示线程 ID
    • CAS(lock, 0, pid) 就表示自旋锁的加锁操作
    • CAS(lock, pid,0) 则表示自旋锁的解锁操作

自旋锁伪代码

while (true) {
//因为判断lock变量的值比CAS操作更快,所以先判断lock再调用CAS效率更高
if (lock == 0 && CAS(lock, 0, pid) == 1) 
	return;
	
if (CPU_count > 1 ) { 
	//如果是多核CPU,“忙等待”才有意义
	for (n = 1; n < 2048; n <<= 1) {
		//pause的时间,应当越来越长
		for (i = 0; i < n; i++) 
			pause();//CPU专为自旋锁设计了pause指令
	if (lock == 0 && CAS(lock, 0, pid)) 
	return;//pause后再尝试获取锁
	}
}

sched_yield();//单核CPU,或者长时间不能获取到锁,应主动休眠,让出CPU
}
自旋锁相关API 定义自旋锁
spinlock_t s_lock ;
初始化自旋锁
int spin_lock_init(spinlock_t *lock);
获取自旋锁函数
void spin_lock(spinlock_t *lock);
尝试获取自旋锁函数
int spin_trylock(spinlock_t *lock);
  • 尝试获取一次,获取成功返回“true”,获取失败返回“false”。程序继续往下执行
释放自旋锁
void spin_unlock(spinlock_t *lock);
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/456979.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号