當(dāng)我們涉及多線程開(kāi)發(fā)時(shí)就必然涉及線程間的數(shù)據(jù)安全問(wèn)題。iOS中線程同步技術(shù)的方案之一就是給數(shù)據(jù)上鎖。線程鎖有很多種,如下所示:
os_unfair_lock
pthread_mutex
dispatch_semaphore
dispatch_queue(DISPATCH_QUEUE_SERIAL)
NSLock
NSRecursiveLock
NSCondition
NSConditionLock
@synchronized
1.os_unfair_lock
導(dǎo)入頭文件
#import <os/lock.h>
用法如下:
//創(chuàng)建鎖
os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
//嘗試加鎖,添加成功返回true,添加失敗返回false
bool r = os_unfair_lock_trylock(&lock);
//強(qiáng)制加鎖
os_unfair_lock_lock(&lock);
// 解鎖
os_unfair_lock_unlock(&lock);
其中os_unfair_lock_trylock方法與os_unfair_lock_lock方法,我們使用一個(gè)加鎖即可。
2.pthread_mutex
導(dǎo)入頭文件
#import <pthread/pthread.h>
用法如下:
//創(chuàng)建鎖屬性,也可不設(shè)置鎖屬性
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
/*
* Mutex type attributes
*/
// #define PTHREAD_MUTEX_NORMAL 0
// #define PTHREAD_MUTEX_ERRORCHECK 1
// #define PTHREAD_MUTEX_RECURSIVE 2
// #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
//PTHREAD_MUTEX_RECURSIVE設(shè)置為該屬性時(shí),為遞歸鎖,在遞歸函數(shù)中使用,保證遞歸函數(shù)調(diào)用僅一個(gè)線程
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
//創(chuàng)建鎖
pthread_mutex_t mutexLock;
//可設(shè)置屬性
// pthread_mutex_init(&mutexLock, &attr);
pthread_mutex_init(&mutexLock, NULL);
//嘗試加鎖,返回1代表加鎖成功
// int r = pthread_mutex_trylock(&mutexLock);
//強(qiáng)制加鎖
pthread_mutex_lock(&mutexLock);
// 解鎖
pthread_mutex_unlock(&mutexLock);
//銷(xiāo)毀鎖
pthread_mutexattr_destroy(&attr);
pthread_mutex_destroy(&mutexLock);
pthread_mutex也可以創(chuàng)建條件鎖,當(dāng)我們遇到以下情況時(shí)可以使用條件鎖:

開(kāi)始執(zhí)行任務(wù)1和任務(wù)2,但是任務(wù)1依賴(lài)于任務(wù)2,必須任務(wù)2執(zhí)行完畢才執(zhí)行任務(wù)1,我們可以在任務(wù)1前增加條件鎖,在任務(wù)2完成后打開(kāi)條件鎖,就滿足我們的業(yè)務(wù)開(kāi)發(fā)需求。
相關(guān)代碼方法如下:
//創(chuàng)建鎖
pthread_mutex_t mutexLock;
//可設(shè)置屬性
pthread_mutex_init(&mutexLock, NULL);
//初始化條件
pthread_cond_t cond;
pthread_cond_init(&cond, NULL);
//進(jìn)入休眠,等待喚醒
pthread_cond_wait(&self->_cond, &self->_mutexLock);
//激活所有等待該條件的線程
// pthread_cond_broadcast(&self->_cond);
//激活一個(gè)等待該條件的線程
pthread_cond_signal(&self->_cond);
//銷(xiāo)毀資源
pthread_mutex_destroy(&(self->_mutexLock));
pthread_cond_destroy(&self->_cond);
3.dispatch_semaphore
信號(hào)量的使用
GCD提供了信號(hào)量函數(shù),提供我們進(jìn)行線程安全操作,當(dāng)信號(hào)量為0時(shí)等待操作,信號(hào)量大于0是,繼續(xù)執(zhí)行操作,,主要流程如下:
1、創(chuàng)建信號(hào)量對(duì)象,確定信號(hào)初始值
2、開(kāi)始執(zhí)行操作前檢查是否需要等待,執(zhí)行函數(shù)dispatch_semaphore_wait,如果當(dāng)前的信號(hào)量為0則阻塞,等待信號(hào)量大于0時(shí)繼續(xù)執(zhí)行,執(zhí)行函數(shù)完畢會(huì)使信號(hào)量減一。當(dāng)一個(gè)任務(wù)執(zhí)行完畢時(shí)我們需要調(diào)用dispatch_semaphore_signal函數(shù),告訴系統(tǒng)一個(gè)任務(wù)執(zhí)行完畢,調(diào)用后會(huì)使信號(hào)量加1。dispatch_semaphore_wait和dispatch_semaphore_signal函數(shù)應(yīng)當(dāng)成對(duì)存在,有特別需求也可以不成對(duì)存在。當(dāng)初始信號(hào)量為1時(shí),我們可以用作線程安全鎖進(jìn)行使用,代碼如下:
- (void)dispatch_semaphore {
dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(3);
for (int i = 0; i < 10; i++) {
dispatch_semaphore_wait(semaphore_t, DISPATCH_TIME_FOREVER);
dispatch_async(self.concurrent_queue, ^{
int t = rand() % 5;
sleep(t);
NSLog(@"dispatch_semaphore===%d===%@===%d",i,[NSThread currentThread],t);
dispatch_semaphore_signal(semaphore_t);
});
}
NSLog(@"end");
}
4.dispatch_queue
創(chuàng)建串形隊(duì)列相當(dāng)于加上了安全鎖
代碼如下
dispatch_queue_create("", DISPATCH_QUEUE_SERIAL)
5.NSLock
NSLock是對(duì)mutex的面相對(duì)象封裝,使用比較簡(jiǎn)單。
代碼如下:
//創(chuàng)建對(duì)象
NSLock *lock = [[NSLock alloc] init];
//上鎖
[lock lock]
//解鎖
[lock unlock];
6.NSRecursiveLock
NSRecursiveLock是mutex遞歸鎖的面向?qū)ο蠓庋b,使用簡(jiǎn)單。代碼如下:
//創(chuàng)建對(duì)象
NSRecursiveLock* lock = [[NSRecursiveLock alloc] init];
//上鎖
[lock lock];
//解鎖
[lock unlock];
7.NSCondition
NSCondition是對(duì)mutex和cond的封裝,代碼如下:
//創(chuàng)建對(duì)象
NSCondition *condition = [[NSCondition alloc] init];
//激活所有等待該條件的線程
//[self.condition broadcast];
//激活一個(gè)等待該條件的線程
[self.condition signal];
//進(jìn)入休眠,等待喚醒
[self.condition wait];
8.NSConditionLock
NSConditionLock是對(duì)NSCondition的進(jìn)一步封裝,可以設(shè)置具體的條件值。用法如下:
//創(chuàng)建條件2的鎖
NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:2];
self.conditionLock = lock;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//等待條件1
[self.conditionLock lockWhenCondition:1];
NSLog(@"1");
//打開(kāi)條件3
[self.conditionLock unlockWithCondition:3];
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//等待條件4
[self.conditionLock lockWhenCondition:4];
NSLog(@"2");
//打開(kāi)條件1
[self.conditionLock unlockWithCondition:1];
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//等待條件2
[self.conditionLock lockWhenCondition:2];
NSLog(@"3");
//打開(kāi)條件4
[self.conditionLock unlockWithCondition:4];
});
打印順序?yàn)?、2、1
9.synchronized
synchronized使用很簡(jiǎn)單,把代碼寫(xiě)在大括號(hào)里面就行。
@synchronized (<#token#>) {
<#statements#>
}
例如:
@synchronized (self) {
self.count = self.count + 1;
}