iOS 鎖的使用

參考 demo

參考的文章:
iOS開發(fā)中的11種鎖以及性能對比
多線程-線程安全

結(jié)論:

  • 自旋鎖性能 > 信號量 > 互斥鎖
  • 等待互斥鎖的線程會(huì)進(jìn)行休眠狀態(tài)避免繼續(xù)占用CPU資源
  • 互斥的實(shí)現(xiàn)涉及到了可能發(fā)生的內(nèi)核態(tài)切換,線程休眠、喚醒等,如果臨界執(zhí)行代碼足夠小而快,不適合互斥鎖
  • 等待自旋鎖的線程會(huì)進(jìn)入while循環(huán)中空轉(zhuǎn)等待
  • 自旋的實(shí)現(xiàn)邏輯足夠簡單,只要標(biāo)記位的修改被設(shè)計(jì)為原子操作,就能保證多線程環(huán)境下的安全。對比互斥方案,自旋沒有線程切換、休眠喚醒的開銷。但是空轉(zhuǎn)的代碼會(huì)導(dǎo)致CPU在等待期間是滿負(fù)荷執(zhí)行的,如果加鎖的代碼不夠小而快,甚至?xí)苯佑绊懙匠绦虻倪\(yùn)行

互斥鎖

  1. NSLock
//初始化
self.array = @[].mutableCopy;
self.lock = [[NSLock alloc] init];
self.lock.name = @"com.example.lock.nslock";

//多線程,訪問臨界區(qū)
[self.lock lock];
[self.array addObject:number];
[self.lock unlock];

  1. pthread_mutex_t
//頭文件
#import <pthread.h>

//定義
pthread_mutex_t mutex;

//初始化
self.array = @[].mutableCopy;
pthread_mutex_init(&mutex,NULL);

//多線程,訪問臨界區(qū)
pthread_mutex_lock(&mutex);
[self.array addObject:number];
pthread_mutex_unlock(&mutex);

//dealloc
pthread_mutex_destroy(&mutex);

  1. @synchronized
@synchronized (self) {
    [self.array addObject:number];
}

自旋鎖

  1. OSSpinLock (廢棄)

存在的問題,優(yōu)先級反轉(zhuǎn):

如果一個(gè)低優(yōu)先級的線程獲得鎖并訪問共享資源,這時(shí)一個(gè)高優(yōu)先級的線程也嘗試獲得這個(gè)鎖,它會(huì)處于 spin lock 的忙等狀態(tài)從而占用大量 CPU。此時(shí)低優(yōu)先級線程無法與高優(yōu)先級線程爭奪 CPU 時(shí)間,從而導(dǎo)致任務(wù)遲遲完不成、無法釋放 lock

#import <libkern/OSAtomic.h>

OSSpinLock lock = OS_SPINLOCK_INIT;
OSSpinLockLock(&lock);
//臨界區(qū)代碼
OSSpinLockUnlock(&lock);
  1. os_unfair_lock(OSSpinLock的替代方案,iOS10.0以后可用)
#import <os/lock.h>

os_unfair_lock_t unfairLock;
unfairLock = &(OS_UNFAIR_LOCK_INIT);
os_unfair_lock_lock(unfairLock);
//臨界區(qū)代碼
os_unfair_lock_unlock(unfairLock);

信號量

dispatch_semaphore_create(long value); // 創(chuàng)建信號量
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); // 等待信號量
//臨界區(qū)的代碼
dispatch_semaphore_signal(dispatch_semaphore_t deem); // 發(fā)送信號量

使用barrier

dispatch_queue_t queue = dispatch_queue_create("queue.concurrent", DISPATCH_QUEUE_CONCURRENT);

__block int value = 1;

dispatch_async(queue, ^{
    NSLog(@"task1,value = %d",value);
});

dispatch_async(queue, ^{
    NSLog(@"task2, value = %d",value);
});

dispatch_barrier_async(queue, ^{
    value = 2;
    NSLog(@"barrier, modify value to %d", value);
});

dispatch_async(queue, ^{
    NSLog(@"task3, value = %d",value);
});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容