美文网首页
iOS 自己实现一个递归自旋锁

iOS 自己实现一个递归自旋锁

作者: BossMoney | 来源:发表于2021-08-27 16:54 被阅读0次

什么是自旋锁?

是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。

获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务,使用这种锁会造成busy-waiting,这样会使cpu资源浪费。所以自旋锁一般使用在加锁代码段执行耗时非常短的地方。

使用swift实现一个自旋锁

public class BMLock {
    private var locked = 0
    
    func lock() {
        while !OSAtomicCompareAndSwapLongBarrier(0, 1, &locked) {}
    }
    
    func unlock() {
        OSAtomicCompareAndSwapLongBarrier(1, 0, &locked)
    }
}
func OSAtomicCompareAndSwapLongBarrier(_ __oldValue: Int, _ __newValue: Int, _ __theValue: UnsafeMutablePointer<Int>!) -> Bool

这里使用了CompareAndSet(CAS)。
伪代码是这样的

func OSAtomicCompareAndSwapLongBarrier(_ __oldValue: Int, _ __newValue: Int, _ __theValue: Int) -> Bool {
        if oldValue == theValue {
            theValue = newValue
            return true
        } else {
            return false
        }
}

如果需要递归

public class BMLock {
    
    private var thread:UnsafeMutableRawPointer?
    private var count = 0
    
    public func lock() {
        if OSAtomicCompareAndSwapPtrBarrier(pthread_self(), pthread_self(), &thread) {
            count += 1
            return
        }
        while !OSAtomicCompareAndSwapPtrBarrier(nil, pthread_self(), &thread) {usleep(10)}//usleep10提高性能
    }
    
    public func unlock() {
        if count > 0 {
            count -= 1
        } else {
            OSAtomicCompareAndSwapPtrBarrier(pthread_self(), nil, &thread)
        }
    }
    
}

CompareAndSet通过原子操作实现了CAS操作,最底层基于汇编语言实现。

简单说一下原子操作的概念,“原子”代表最小的单位,所以原子操作可以看做最小的执行单位,该操作在执行完毕前不会被任何其他任务或事件打断。

这里还需要使用带barrier结尾的方法。

Memory ordering

Memory ordering用来描述系统中的processor对内存的操作如何对其它processor可见(可见的定义见前面的描述)。同时需要说明的是,大多数文献都采用reorder这个表达方式,是从执行等价的角度来描述的:比如P1上执行两个写操作WRITE(A)和WRITE(B),如果对于观察者P2来说P1|WRITE(B)先于P2|WRITE(A)可见,那么就可以认为P1的写操作发生了reorder。对读操作也是类似的。
影响memoryordering的因素很多,包括:
体系结构,X86和ARM的memory ordering就截然不同;
ARM的memory order属于weak order,与SC差距极大。如果涉及到免锁设计,对ARM体系结构, memorybarrier的使用是不可避免的。

自旋锁缺点

自旋锁会存在优先级反转问题。
具体来说,如果一个低优先级的线程获得锁并访问共享资源,这时一个高优先级的线程也尝试获得这个锁,它会处于 spin lock 的忙等状态从而占用大量 CPU。此时低优先级线程无法与高优先级线程争夺 CPU 时间,从而导致任务迟迟完不成、无法释放 lock。

苹果的OSSpinLock因为存在优先级反转问题,在 iOS 10/macOS 10.12 发布时,苹果提供了新的 os_unfair_lock 作为 OSSpinLock 的替代,并且将 OSSpinLock 标记为了 Deprecated。

相关文章

  • iOS 自己实现一个递归自旋锁

    什么是自旋锁? 是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否...

  • iOS锁

    锁的作用:保证线程安全。锁的分类:互斥锁,自旋锁,其它比如条件锁,递归锁,信号量都是上层的封装和实现。 互斥锁 防...

  • 关于自旋锁

    自旋锁是什么? spinlock,不断的自旋(自我循环)尝试获得锁。参考文档:Java中的自旋锁 自旋锁的实现 自...

  • 2018-07-26 抖音面试题汇总

    互斥锁、自旋锁、递归锁啥区别? 都是保证只有一个线程访问对象的锁。互斥会睡眠线程,自选会循环访问,递归是特殊的互斥...

  • C++锁

    锁的种类 互斥锁、条件锁、自旋锁、读写锁、递归锁。 互斥锁 头文件: 类型:pthread_mutex_t, 函数...

  • iOS开发中知道的哪些锁?

    一、自旋锁 A、OSLink 二、互斥锁 A. 递归锁 B. 条件锁 C.普通互斥锁 NSLock 三、GCD锁 ...

  • 互斥锁 自旋锁 递归锁 条件锁 读写锁 互斥锁:pthread_ mutex_t(NSLock基于此封装)每个对象...

  • iOS面试 自己实现一个自旋锁

    自旋锁的原理 作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发交流群:1305955...

  • iOS面试 自己实现一个自旋锁

    面试的时候被问到了,突然有点懵逼,遂自己研究实现一下 自旋锁的原理 如果共享数据已经有其他线程加锁了,线程会以死循...

  • 阅读的好文章

    介绍什么是自旋锁, 从原始自旋锁到CLH锁和MCS锁多线程自旋锁实现方案 codis貌似不支持主备有点可惜codi...

网友评论

      本文标题:iOS 自己实现一个递归自旋锁

      本文链接:https://www.haomeiwen.com/subject/dqbmiltx.html