iOS各種鎖簡(jiǎn)介(上)
本篇文章主要介紹iOS中幾種不同的鎖的實(shí)現(xiàn)方式,既然是簡(jiǎn)介,這里不會(huì)涉及到原理上面的東西,主要還是如何使用。
在開始之前,我們先構(gòu)建一個(gè)測(cè)試類,假設(shè)這個(gè)類是一個(gè)共享資源,提供兩個(gè)方法method1和method2,假設(shè)method1和method2是互斥的,代碼如下:
@implementation TestObject
- (void)method1 {
NSLog(@"%@",NSStringFromSelector(_cmd));
}
- (void)method2 {
NSLog(@"%@",NSStringFromSelector(_cmd));
}
@end
NSLock
NSLock是cocoa提供給我們最基本的鎖對(duì)象,這個(gè)是最簡(jiǎn)單的一個(gè)鎖,NSLock提供了lock和unlock兩個(gè)方法,分別是加鎖和解鎖。NSLock內(nèi)部實(shí)際是封裝了pthread_mutex。使用方法很簡(jiǎn)單,代碼如下:
- (void)lockDemo {
TestObject *obj = [[TestObject alloc] init];
NSLock *lock = [[NSLock alloc] init];
// 線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lock];
[obj method1];
sleep(10);
[lock unlock];
});
// 線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
[lock lock];
[obj method2];
[lock unlock];
});
}
從打印結(jié)果可以看出,線程1獲得鎖之后,線程2會(huì)一直等待,直到線程1釋放鎖(unlock)之后才會(huì)執(zhí)行。
@synchronized
@synchronized的使用方式很簡(jiǎn)單,先看代碼:
- (void)synchronizedDemo {
TestObject *obj = [[TestObject alloc] init];
// 線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(obj) {
[obj method1];
sleep(10);
}
});
// 線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
@synchronized(obj) {
[obj method2];
}
});
}
跟NSLock加鎖的結(jié)果一樣,線程2也是等到線程1釋放鎖之后才執(zhí)行。從代碼中可以看出,@synchronized實(shí)現(xiàn)鎖非常方便,注意:@synchronized指令中使用的obj為鎖的唯一標(biāo)識(shí),只有標(biāo)識(shí)相同的時(shí)候,才滿足互斥。如果上述代碼中線程2@synchronized(obj)中的標(biāo)識(shí)和線程1的不一樣,那么線程2不會(huì)被阻塞。
pthread_mutex_t
pthread_mutex_t是posix下的一個(gè)鎖類型,如果熟悉linux c編程的話會(huì)對(duì)這個(gè)比較熟悉。在iOS下使用也是一樣的,代碼如下:
- (void)pthreadDemo {
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是posix下的API,所以要引入相應(yīng)的頭文件#import <pthread.h>
dispatch_semaphore_t
dispatch_semaphore_t是GCD里面的一個(gè)信號(hào)量機(jī)制,也可以用來做線程同步。其相關(guān)的方法主要有:
dispatch_semaphore_t dispatch_semaphore_create(long value);
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);
dispatch_semaphore_create:創(chuàng)建一個(gè)新的信號(hào)量,value代表信號(hào)量資源的數(shù)量.
dispatch_semaphore_wait: 等待資源釋放,如果此時(shí)dsema大于0,獲得資源,繼續(xù)執(zhí)行,并將信號(hào)量減1。如果dsema=0,阻塞當(dāng)前線程直到其他線程調(diào)dispatch_semaphore_signal釋放信號(hào)量。如果一直等不到信號(hào)量,則到timeout之后再繼續(xù)執(zhí)行。
dispatch_semaphore_signal:釋放一個(gè)資源。
使用代碼如下:
- (void)semaphoreDemo {
TestObject *obj = [[TestObject alloc] init];
dispatch_semaphore_t semphore = dispatch_semaphore_create(1);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semphore, DISPATCH_TIME_FOREVER);
[obj method1];
sleep(5);
dispatch_semaphore_signal(semphore);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
dispatch_semaphore_wait(semphore, DISPATCH_TIME_FOREVER);
[obj method2];
dispatch_semaphore_signal(semphore);
});
}