本文主要討論OC中各種鎖的使用祝闻。首先寄疏,創(chuàng)建一個用來測試的類瞧栗。假設這個測試類是共享的資源,然后method1和method2是互斥的菩彬。
測試類:
#import "TestObject.h"
@implementation TestObject
- (void)method1
{
NSLog(@"%@",NSStringFromSelector(_cmd));
}
- (void)method2
{
NSLog(@"%@",NSStringFromSelector(_cmd));
}
@end
1.使用NSLock實現的鎖
TestObject *obj = [[TestObject alloc] init];
NSLock *lock = [[NSLock alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lock];
[obj method1];
sleep(10);
[lock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);//以保證讓線程2的代碼后執(zhí)行
[lock lock];
[obj method2];
[lock unlock];
});
除lock和unlock方法外缠劝,NSLock還提供了tryLock
和lockBeforeDate
:兩個方法,前一個方法會嘗試加鎖骗灶,如果鎖不可用(已經被鎖住)惨恭,剛并不會阻塞線程,并返回NO耙旦。lockBeforeDate:方法會在所指定Date之前嘗試加鎖脱羡,如果在指定時間之前都不能加鎖,則返回NO免都。
2.使用synchronized關鍵字構建的鎖
TestObject *obj = [[TestObject alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(obj){
[obj method1];
sleep(10);
}
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
@synchronized(obj){
[obj method2];
}
});
@synchronized指令使用的obj為該鎖的唯一標識锉罐,只有當標識相同時,才為滿足互斥绕娘,如果線程2中的@synchronized(obj)
改為@synchronized(other)
,剛線程2就不會被阻塞脓规,@synchronized指令實現鎖的優(yōu)點就是我們不需要在代碼中顯式的創(chuàng)建鎖對象
,便可以實現鎖的機制险领,但作為一種預防措施侨舆,@synchronized塊會隱式的添加一個異常處理例程來保護代碼,該處理例程會在異常拋出的時候自動的釋放互斥鎖绢陌。所以如果不想讓隱式的異常處理例程帶來額外的開銷挨下,你可以考慮使用鎖對象。
3.使用C語言的pthread_mutex_t實現的鎖
TestObject *obj = [[TestObject alloc] init];
__block pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
[obj method1];
sleep(5);
pthread_mutex_unlock(&mutex);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
pthread_mutex_lock(&mutex);
[obj method2];
pthread_mutex_unlock(&mutex);
});
由于pthread_mutex_t定義在C語言中的pthread.h
脐湾,所以導入頭文件要使用#include
臭笆。
4.使用GCD來實現的”鎖”
以上代碼構建多線程我們就已經用到了GCD的dispatch_async
方法,其實在GCD中也已經提供了一種信號機制
秤掌,使用它我們也可以來構建一把”鎖”(從本質意義上講愁铺,信號量
與鎖
是有區(qū)別,具體差異請自行查閱信號量與互斥鎖之間的區(qū)別)
TestObject *obj = [[TestObject alloc] init];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[obj method1];
sleep(10);
dispatch_semaphore_signal(semaphore);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[obj method2];
dispatch_semaphore_signal(semaphore);
});
以上就是常用的鎖機制闻鉴,在網上查資料都說OSSpinLock
自旋鎖效率是最高的茵乱,但是目前很多人都說自旋鎖已經不再安全。如果算上OSSpinLock椒拗,各種鎖的效率如下
OSSpinLock > pthread_mutex > NSLock > semaphore > @Sych
如果有有關于OSSpinLock是否安全的問題會及時更新。