CPU底层锁指令

任何编程语言的锁操作本质都依赖于 CPU 底层锁指令。操作系统封装 CPU 底层锁指令实现了自旋锁和互斥锁两种基础锁,并通过系统调用接口提供给用户程序。
Linux 中的自旋锁由 spinlock_t 结构体表示,相应的系统调用函数包括

  • spin_lock():获取自旋锁
  • spin_unlock():释放自旋锁

Linux 中的互斥锁由 mutex_t 结构体表示,相应的系统调用函数包括

  • mutex_lock():获取互斥锁
  • mutex_unlock():释放互斥锁

x86 锁指令

锁指令在单核显然是原子的,在多核情况下会通过锁总线的方式保证原子性

# TAS指令,将destination的值和source的值进行交换,可以理解成写destination并返回原值
lock xchg destination source
# CAS指令,将destination的值与compare的值进行比较,如果相等就给destination赋exchange的值,如果不相等就不变
lock cmpxchg destination, exchange, compare
# 将value加到destination
lock add value, destination
# 将destination减去value
lock sub value, destination
# destination加1
lock inc destination
# destination减1
lock dec destination

TAS 指令实现忙等待锁

lock:
    lock xchg lock_var, %eax; # 将lock_var值和eax寄存器值交换
    test %eax, %eax; # 判断eax寄存器的值是否为0
    jnz lock; # 如果不为0则继续自旋
    # ...执行临界区代码

CAS 指令实现无锁计数器

retry:
    mov count %eax; # count值写入eax寄存器
    mov %eax %ebx; # eax寄存器值写入ebx寄存器
    inc %eax; # eax寄存器加1
    lock cmpxchg count, %eax, %ebx; # 如果count和ebx想等,就将eax寄存器的值写入count
    jne retry; # 如果上一步失败就跳转到retry
    # ...执行临界区代码

CAS 指令实现无等待锁

下面的过程可以看作是一个系统调用函数

# 全局变量
int mutex = 0;

# 加锁过程
while(!cas(mutex,1,0)) {
    # 保存当前线程上下文
    # 将当前线程从运行态切换到阻塞态
    # 跳转到线程调度函数,根据调度算法选择一个就绪线程将其切换到运行态
    # 加载该线程的线程上下文
    # 将该线程第一条指令的地址写入程序计数器
}

# 解锁过程
mutex = 0;
# 查看阻塞在mutex上的所有线程
# 按照某种算法选择一个线程并将其从阻塞态切换到就绪态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值