iOS笔记系列目录

一 自旋锁

是一种用于保护多线程共享资源的锁,与一般互斥锁(mutex)不同之处在于当自旋锁尝试获取锁时以忙等待(busy waiting)的形式不断地循环检查锁是否可用。当上一个线程的任务没有执行完毕的时候(被锁住),那么下一个线程会一直等待(不会睡眠),当上一个线程的任务执行完毕,下一个线程会立即执行。
在多CPU的环境中,对持有锁较短的程序来说,使用自旋锁代替一般的互斥锁往往能够提高程序的性能。
优点
自旋锁不会引起调用者睡眠,所以不会进行线程调度,CPU时间片轮转等耗时操作。所有如果能在很短的时间内获得锁,自旋锁的效率远高于互斥锁。
缺点
自旋锁一直占用CPU,他在未获得锁的情况下,一直运行--自旋,所以占用着CPU,如果不能在很短的时间内获得锁,这无疑会使CPU效率降低。

小结
效率高,但是耗费资源,不能实现递归调用。

二 互斥锁

当上一个线程的任务没有执行完毕的时候(被锁住),那么下一个线程会进入睡眠状态等待任务执行完毕,当上一个线程的任务执行完毕,下一个线程会自动唤醒然后执行任务。

三 递归锁

递归锁允许同一个线程在未释放其拥有的锁时反复对该锁进行加锁操作。

// _lock = [[NSRecursiveLock alloc] init]; // pthread_mutex_t可替换成NSRecursiveLock

static pthread_mutex_t pLock;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); //初始化attr并且给它赋予默认
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); //设置锁类型,这边是设置为递归锁
pthread_mutex_init(&pLock, &attr);
pthread_mutexattr_destroy(&attr); //销毁一个属性对象,在重新进行初始化之前该结构不能重新使用

//1.线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    static void (^RecursiveBlock)(int);
    RecursiveBlock = ^(int value) {
//        [_lock lock];
        pthread_mutex_lock(&pLock);
        if (value > 0) {
            NSLog(@"value: %d", value);
            RecursiveBlock(value - 1);
        }
//        [_lock unlock];
        pthread_mutex_unlock(&pLock);
    };
    RecursiveBlock(5);
});

四 总结

  • 自旋锁会忙等,即在访问被锁资源时,调用者线程不会休眠,而是不停循环在那里,直到被锁资源释放锁。
  • 互斥锁会休眠,即在访问被锁资源时,调用者线程会休眠,此时cpu可以调度其他线程工作。直到被锁资源释放锁。此时会唤醒休眠线程。

五 常见的锁

  • 自旋锁

    • atomic
    • OSSpinLock
    • dispatch_semaphore_t (信号量 GCD)
  • 互斥锁

    • os_unfair_lock(替代OSSpinLock)
    • pthread_mutex (含recursive实现方案)
    • @synchronized
    • NSLock (对象锁)
    • NSConditionLock (条件锁)
    • NSCondition
    • NSRecursiveLock (递归锁)

六 常见锁的性能

image.png
图片来源@ibireme

七 常见锁的使用

iOS中常见的10种锁


Adrenine
9 声望3 粉丝

最怕一生碌碌无为却道平凡难能可贵!