iOS 十種線程鎖

鎖 是什麼意思?ios

  • 咱們在使用多線程的時候多個線程可能會訪問同一塊資源,這樣就很容易引起數據錯亂和數據安全等問題,這時候就須要咱們保證每次只有一個線程訪問這一塊資源,鎖 應運而生。安全

  • 這裏順便提一下,上鎖的兩種方式trylock和lock使用場景:多線程

 

當前線程鎖失敗,也能夠繼續其它任務,用 trylock 合適性能

當前線程只有鎖成功後,纔會作一些有意義的工做,那就 lock,不必輪詢 trylock測試

注:如下大部分鎖都會提供trylock接口,再也不做解釋spa

 

性能圖線程

 

<準備操做>對象

 

測試代碼blog

#define RHTICK   NSDate *startTime = [NSDate date];遞歸

#define RHTOCK   NSLog(@"==========Time: %f", -[startTime timeIntervalSinceNow]);

NSUInteger count = 1000*10000;//執行一千萬次

RHTICK

for(int i=0; i<count; i++) {

加鎖

解鎖

}

RHTOCK

注:測試中執行時間會波動,因此我取的平均值.

 

1、OSSpinLock (自旋鎖)

 

測試中效率最高的鎖, 不過經YYKit做者確認, OSSpinLock已經再也不線程安全,OSSpinLock有潛在的優先級反轉問題.再也不安全的 OSSpinLock;

 

  • 0.097348s

 

須要導入頭文件

#import <libkern/OSAtomic.h>

// 初始化

 OSSpinLock spinLock = OS_SPINLOCK_INIT;

// 加鎖

OSSpinLockLock(&spinLock);

// 解鎖

OSSpinLockUnlock(&spinLock);

// 嘗試加鎖,能夠加鎖則當即加鎖並返回 YES,反之返回 NO

OSSpinLockTry(&spinLock)

/*

注:蘋果爸爸已經在iOS10.0之後廢棄了這種鎖機制,使用os_unfair_lock 替換,

顧名思義可以保證不一樣優先級的線程申請鎖的時候不會發生優先級反轉問題.

*/

 

2、os_unfair_lock(自旋鎖)

 

  • 0.171789s

 

須要導入頭文件

#import <os/lock.h>

// 初始化

 os_unfair_lock unfair_lock = OS_UNFAIR_LOCK_INIT;

// 加鎖

os_unfair_lock_lock(&unfair_lock);

// 解鎖

os_unfair_lock_unlock(&unfair_lock);

// 嘗試加鎖,能夠加鎖則當即加鎖並返回 YES,反之返回 NO

os_unfair_lock_trylock(&unfair_lock);

/*

注:解決不一樣優先級的線程申請鎖的時候不會發生優先級反轉問題.

不過相對於 OSSpinLock , os_unfair_lock性能方面減弱了許多.

*/

 

3、dispatch_semaphore (信號量)

 

  • 0.155043s

 

// 初始化

dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(1);

// 加鎖

dispatch_semaphore_wait(semaphore_t,DISPATCH_TIME_FOREVER);

// 解鎖

dispatch_semaphore_signal(semaphore_t);

/*

注: dispatch_semaphore  其餘兩個功能

1.還能夠起到阻塞線程的做用.

2.能夠實現定時器功能,這裏不作過多介紹.

*/

 

4、pthread_mutex(互斥鎖)

 

  • 0.262592s

 

須要導入頭文件

#import <pthread/pthread.h>

// 初始化(兩種)

1.普通初始化

pthread_mutex_t mutex_t;

pthread_mutex_init(&mutex_t, NULL); 

2.宏初始化

pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;

// 加鎖

pthread_mutex_lock(&mutex_t);

// 解鎖

pthread_mutex_unlock(&mutex_t);

// 嘗試加鎖,能夠加鎖時返回的是 0,不然返回一個錯誤

pthread_mutex_trylock(& mutex_t)

 

5、NSLock(互斥鎖、對象鎖)

 

  • 0.283196s

 

// 初始化

NSLock *_lock = [[NSLock alloc]init];

// 加鎖

[_lock lock];

// 解鎖

[_lock unlock];

// 嘗試加鎖,能夠加鎖則當即加鎖並返回 YES,反之返回 NO

[_lock tryLock];

 

6、NSCondition(條件鎖、對象鎖)

 

  • 0.293046s

 

// 初始化

NSCondition *_condition= [[NSCondition alloc]init];

// 加鎖

[_condition lock];

// 解鎖

[_condition unlock];

/*

其餘功能接口

wait 進入等待狀態

waitUntilDate:讓一個線程等待必定的時間

signal 喚醒一個等待的線程

broadcast 喚醒全部等待的線程

注: 所測時間波動太大, 有時候會快於 NSLock, 我取得中間值.

*/

 

7、NSConditionLock(條件鎖、對象鎖)

 

  • 0.950285s

 

// 初始化

NSConditionLock *_conditionLock = [[NSConditionLock alloc]init];

// 加鎖

[_conditionLock lock];

// 解鎖

[_conditionLock unlock];

// 嘗試加鎖,能夠加鎖則當即加鎖並返回 YES,反之返回 NO

[_conditionLock tryLock];

/*

其餘功能接口

- (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER; //初始化傳入條件

- (void)lockWhenCondition:(NSInteger)condition;//條件成立觸發鎖

- (BOOL)tryLockWhenCondition:(NSInteger)condition;//嘗試條件成立觸發鎖

- (void)unlockWithCondition:(NSInteger)condition;//條件成立解鎖

- (BOOL)lockBeforeDate:(NSDate *)limit;//觸發鎖 在等待時間以內

- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;//觸發鎖 條件成立 而且在等待時間以內

*/

 

8、NSRecursiveLock(遞歸鎖、對象鎖)

 

  • 0.473536s

 

// 初始化

NSRecursiveLock *_recursiveLock = [[NSRecursiveLock alloc]init];

// 加鎖

[_recursiveLock lock];

// 解鎖

[_recursiveLock unlock];

// 嘗試加鎖,能夠加鎖則當即加鎖並返回 YES,反之返回 NO

[_recursiveLock tryLock];

/*

注: 遞歸鎖能夠被同一線程屢次請求,而不會引發死鎖。

即在同一線程中在未解鎖以前還能夠上鎖, 執行鎖中的代碼。

這主要是用在循環或遞歸操做中。

- (BOOL)lockBeforeDate:(NSDate *)limit;//觸發鎖 在等待時間以內

*/

 

9、@synchronized(條件鎖)

 

  • 1.101924s

 

// 初始化

@synchronized(條件){

}

     更多關於@synchronized;

 

10、pthread_mutex(recursive)(遞歸鎖)

 

  • 0.372398s

 

// 初始化

pthread_mutex_t mutex_t;

pthread_mutexattr_t attr;

pthread_mutexattr_init(&attr); //初始化attr而且給它賦予默認pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); //設置鎖類型,這邊是設置爲遞歸鎖

pthread_mutex_init(&mutex_t, &attr);

pthread_mutexattr_destroy(&attr); //銷燬一個屬性對象,在從新進行初始化以前該結構不能從新使用

// 加鎖

pthread_mutex_lock(&mutex_t);

// 解鎖

pthread_mutex_unlock(&mutex_t);

/*

注: 遞歸鎖能夠被同一線程屢次請求,而不會引發死鎖。

即在同一線程中在未解鎖以前還能夠上鎖, 執行鎖中的代碼。

這主要是用在循環或遞歸操做中。

*/

 

性能總結

 

OSSpinLock                          0.097348s

dispatch_semaphore                  0.155043s

os_unfair_lock                      0.171789s

pthread_mutex                       0.262592s

NSLock                               0.283196s

pthread_mutex(recursive)            0.372398s

NSRecursiveLock                     0.473536s

NSConditionLock                     0.950285s

@synchronized                       1.101924s

 

注:建議正常鎖功能用 pthread_mutex ,os_unfair_lock (適配低版本)

相關文章
相關標籤/搜索