自旋锁简介

自旋锁属于一种互斥锁。

1 基于硬件原语1:测试并设置指令

原子指令的伪代码:

int TestAndSet(int* old_ptr, int new) {
    int old = *old_ptr;
    *old_ptr = new;
    return old;
}

自旋锁实现:

typedef struct lock_t {
    int flag;
} lock_t;

void init(lock_t* lock) {
    lock->flag = 0;
}

void lock(lock_t* lock) {
    while (TestAndSet(&lock->flag, 1) == 1)
        ; // 自旋
}

void unlock(lock_t* lock) {
    lock->flag = 0;
}

含义:
flag=1表示锁被持有,flag=0表示锁未被持有;
一个线程设置flag=1,就表示这个线程持有了该锁;
一个线程设置flag=0,就表示这个线程释放了该锁;

分析:
(1)如果没有其他线程持有锁时,即flag=0,线程1调用lock(),TestAndSet设置flag=1并返回0, 跳出循环,此时线程1持有该锁。
(2)如果有其他线程持有锁时,即flag=1,线程1调用lock(),TestAndSet不断地设置flag=1并返回1,开始自旋。直到其他线程不再持有锁时,flag=0,TestAndSet设置flag=1返回0,跳出循环,此时线程1持有锁。

2 基于硬件原语2:比较并交换指令

原子指令的伪代码:

int CompareAndSwap(int* ptr, int expect, int new) {
    int actual = *ptr;
    if (actual == expect) {
        *ptr = new;
    }
    return actual;
}

自旋锁实现:

typedef struct lock_t {
    int flag;
} lock_t;

void init(lock_t* lock) {
    lock->flag = 0;
}

void lock(lock_t* lock) {
    while (CompareAndSwap(&lock->flag, 0, 1) == 1)
        ; // 自旋
}

void unlock(lock_t* lock) {
    lock->flag = 0;
}

含义:
flag=1表示锁被持有,flag=0表示锁未被持有;
一个线程设置flag=1,就表示这个线程持有了该锁;
一个线程设置flag=0,就表示这个线程释放了该锁;

分析:
(1)如果没有其他线程持有锁时,即flag=0,线程1调用lock(),CompareAndSwap设置flag=1并返回0, 跳出循环,此时线程1持有该锁。
(2)如果有其他线程持有锁时,即flag=1,线程1调用lock(),CompareAndSwap不断地返回1,开始自旋。直到其他线程不再持有锁时,flag=0,CompareAndSwap设置flag=1返回0,跳出循环,此时线程1持有锁。

3 基于硬件原语3:获取并增加指令

与前两种相比,可以保证所有线程都能抢到锁。避免一个线程一直自旋。

4 结论

自旋锁的忙等会占用CPU资源,需要使用操作系统级别的原语让出CPU。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值