在iOS開發(fā)中,經(jīng)常會(huì)用到多線程開發(fā)的情況,這時(shí)候如果多個(gè)線程同時(shí)訪問(wèn)同一塊資源時(shí),就很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全的問(wèn)題,這個(gè)時(shí)候我們就需要有一個(gè)方法來(lái)保證每次只有一個(gè)線程訪問(wèn)這一塊資源,這個(gè)方法就是鎖。
iOS中一共有8中常用的鎖,我們用YY大神的一張圖來(lái)看一下這些鎖的性能。

OSSpinLock 自旋鎖
OSSpinLock 自旋鎖在圖表中可以看到,性能是最高的,大概在150us,但是YY大神在不再安全的 OSSpinLock中說(shuō)道OSSpinLock自旋鎖已經(jīng)不再安全了。
而且也可以看到OSSpinLock已經(jīng)在iOS 10.0之后廢棄了。

好了,接下來(lái)看一下OSSpinLock中的方法。
OS_SPINLOCK_INIT: 默認(rèn)值為 0,在 locked 狀態(tài)時(shí)就會(huì)大于 0,unlocked狀態(tài)下為 0
OSSpinLockLock(&oslock):上鎖,參數(shù)為 OSSpinLock 地址
OSSpinLockUnlock(&oslock):解鎖,參數(shù)為 OSSpinLock 地址
OSSpinLockTry(&oslock):嘗試加鎖,可以加鎖則立即加鎖并返回 YES,反之返回 NO
接下來(lái)我們測(cè)試一下,比如下面一段代碼中,我們開啟兩個(gè)異步線程。
- (void)setOSSpinLock
{
__block OSSpinLock ossPinLock = OS_SPINLOCK_INIT;
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 10;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 20;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
});
}
可以看到打印出來(lái)的數(shù)據(jù)都是錯(cuò)亂的:
2018-04-23 16:33:12.655341+0800 LockDemo[88725:6234113] 當(dāng)前線程:<NSThread: 0x604000270d00>{number = 3, name = (null)},number=10
2018-04-23 16:33:12.655341+0800 LockDemo[88725:6234116] 當(dāng)前線程:<NSThread: 0x60000026f340>{number = 4, name = (null)},number=10
2018-04-23 16:33:12.655651+0800 LockDemo[88725:6234116] 當(dāng)前線程:<NSThread: 0x60000026f340>{number = 4, name = (null)},number=40
2018-04-23 16:33:12.655655+0800 LockDemo[88725:6234113] 當(dāng)前線程:<NSThread: 0x604000270d00>{number = 3, name = (null)},number=40
這時(shí)候,我們添加一下上OSSpinLock自旋鎖:
首先引入OSSpinLock自旋鎖的庫(kù):
#import <libkern/OSAtomic.h>
- (void)setOSSpinLock
{
__block OSSpinLock ossPinLock = OS_SPINLOCK_INIT;
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,OSSpinLock上鎖",[NSThread currentThread]);
OSSpinLockLock(&ossPinLock);
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 10;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
NSLog(@"當(dāng)前線程:%@,OSSpinLock解鎖",[NSThread currentThread]);
OSSpinLockUnlock(&ossPinLock);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,OSSpinLock上鎖",[NSThread currentThread]);
OSSpinLockLock(&ossPinLock);
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 20;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
NSLog(@"當(dāng)前線程:%@,OSSpinLock解鎖",[NSThread currentThread]);
OSSpinLockUnlock(&ossPinLock);
});
}
可以看到打印的數(shù)據(jù):
2018-04-23 16:34:40.764216+0800 LockDemo[88797:6236783] 當(dāng)前線程:<NSThread: 0x60000027dcc0>{number = 3, name = (null)},OSSpinLock上鎖
2018-04-23 16:34:40.764216+0800 LockDemo[88797:6236781] 當(dāng)前線程:<NSThread: 0x60000027da40>{number = 4, name = (null)},OSSpinLock上鎖
2018-04-23 16:34:40.764450+0800 LockDemo[88797:6236783] 當(dāng)前線程:<NSThread: 0x60000027dcc0>{number = 3, name = (null)},number=10
2018-04-23 16:34:40.764577+0800 LockDemo[88797:6236783] 當(dāng)前線程:<NSThread: 0x60000027dcc0>{number = 3, name = (null)},number=20
2018-04-23 16:34:40.764736+0800 LockDemo[88797:6236783] 當(dāng)前線程:<NSThread: 0x60000027dcc0>{number = 3, name = (null)},OSSpinLock解鎖
2018-04-23 16:34:40.766647+0800 LockDemo[88797:6236781] 當(dāng)前線程:<NSThread: 0x60000027da40>{number = 4, name = (null)},number=20
2018-04-23 16:34:40.766910+0800 LockDemo[88797:6236781] 當(dāng)前線程:<NSThread: 0x60000027da40>{number = 4, name = (null)},number=40
2018-04-23 16:34:40.768117+0800 LockDemo[88797:6236781] 當(dāng)前線程:<NSThread: 0x60000027da40>{number = 4, name = (null)},OSSpinLock解鎖
dispatch_semaphore 信號(hào)量
信號(hào)量是僅次于自旋鎖的方法,使用的是GCD提供的API:
dispatch_semaphore_create 創(chuàng)建一個(gè)Semphore并初始化信號(hào)的總量。
dispatch_semaphore_signal 發(fā)送一個(gè)信號(hào),讓信號(hào)總量加1。
dispatch_semaphore_wait 可以使總信號(hào)量減1,讓信號(hào)總量為0時(shí)就會(huì)一直等待,否則就可以正常執(zhí)行。
這次我們就不上測(cè)試的代碼了,直接放上增加信號(hào)量的代碼:
- (void)setSemaphore
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_time_t overTime = dispatch_time(DISPATCH_TIME_NOW, 3.0f * NSEC_PER_SEC);
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,semaphore信號(hào)量+1",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 10;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
NSLog(@"當(dāng)前線程:%@,semaphore信號(hào)量-1",[NSThread currentThread]);
dispatch_semaphore_wait(semaphore, overTime);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,semaphore信號(hào)量+1",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 20;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
NSLog(@"當(dāng)前線程:%@,semaphore信號(hào)量-1",[NSThread currentThread]);
dispatch_semaphore_wait(semaphore, overTime);
});
}
打印結(jié)果:
2018-04-23 17:05:22.368340+0800 LockDemo[89577:6266694] 當(dāng)前線程:<NSThread: 0x60000026ed00>{number = 3, name = (null)},semaphore信號(hào)量+1
2018-04-23 17:05:22.368340+0800 LockDemo[89577:6266693] 當(dāng)前線程:<NSThread: 0x60000026ed80>{number = 4, name = (null)},semaphore信號(hào)量+1
2018-04-23 17:05:22.368625+0800 LockDemo[89577:6266694] 當(dāng)前線程:<NSThread: 0x60000026ed00>{number = 3, name = (null)},number=10
2018-04-23 17:05:22.368630+0800 LockDemo[89577:6266693] 當(dāng)前線程:<NSThread: 0x60000026ed80>{number = 4, name = (null)},number=10
2018-04-23 17:05:22.368763+0800 LockDemo[89577:6266694] 當(dāng)前線程:<NSThread: 0x60000026ed00>{number = 3, name = (null)},number=20
2018-04-23 17:05:22.368888+0800 LockDemo[89577:6266694] 當(dāng)前線程:<NSThread: 0x60000026ed00>{number = 3, name = (null)},semaphore信號(hào)量-1
2018-04-23 17:05:22.368887+0800 LockDemo[89577:6266693] 當(dāng)前線程:<NSThread: 0x60000026ed80>{number = 4, name = (null)},number=40
2018-04-23 17:05:22.369799+0800 LockDemo[89577:6266693] 當(dāng)前線程:<NSThread: 0x60000026ed80>{number = 4, name = (null)},semaphore信號(hào)量-1
pthread_mutex 互斥鎖
YY大神在之前的文章中已經(jīng)說(shuō)過(guò)OSSpinLock已經(jīng)不再是線程安全的并把自己開源項(xiàng)目中的OSSpinLock都換成了pthread_mutex。
接下來(lái)我們看一下互斥鎖提供的方法:
pthread_mutex_init(&pLock, NULL);:參數(shù)為 pthread_mutex 地址,第二個(gè)參數(shù)默認(rèn)PTHREAD_MUTEX_NORMAL
pthread_mutex_lock(&pLock):上鎖,參數(shù)為 pthread_mutex 地址
pthread_mutex_unlock(&pLock):解鎖,參數(shù)為 pthread_mutex 地址
pthread_mutex_trylock(&pLock):嘗試加鎖,可以加鎖則立即加鎖并返回 0 ,否者返回一個(gè)錯(cuò)誤提示碼。
接下來(lái)看代碼:
- (void)setPthread_mutex
{
static pthread_mutex_t pLock;
pthread_mutex_init(&pLock, NULL);
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,上鎖",[NSThread currentThread]);
pthread_mutex_lock(&pLock);
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 10;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
NSLog(@"當(dāng)前線程:%@,解鎖",[NSThread currentThread]);
pthread_mutex_unlock(&pLock);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,上鎖",[NSThread currentThread]);
pthread_mutex_lock(&pLock);
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 20;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
NSLog(@"當(dāng)前線程:%@,解鎖",[NSThread currentThread]);
pthread_mutex_unlock(&pLock);
});
}
然后是打印結(jié)果:
2018-04-23 17:13:09.376128+0800 LockDemo[89821:6278824] 當(dāng)前線程:<NSThread: 0x600000474900>{number = 3, name = (null)},上鎖
2018-04-23 17:13:09.376128+0800 LockDemo[89821:6278825] 當(dāng)前線程:<NSThread: 0x6000004744c0>{number = 4, name = (null)},上鎖
2018-04-23 17:13:09.376419+0800 LockDemo[89821:6278824] 當(dāng)前線程:<NSThread: 0x600000474900>{number = 3, name = (null)},number=10
2018-04-23 17:13:09.376547+0800 LockDemo[89821:6278824] 當(dāng)前線程:<NSThread: 0x600000474900>{number = 3, name = (null)},number=20
2018-04-23 17:13:09.376759+0800 LockDemo[89821:6278824] 當(dāng)前線程:<NSThread: 0x600000474900>{number = 3, name = (null)},解鎖
2018-04-23 17:13:09.378000+0800 LockDemo[89821:6278825] 當(dāng)前線程:<NSThread: 0x6000004744c0>{number = 4, name = (null)},number=20
2018-04-23 17:13:09.378627+0800 LockDemo[89821:6278825] 當(dāng)前線程:<NSThread: 0x6000004744c0>{number = 4, name = (null)},number=40
2018-04-23 17:13:09.378846+0800 LockDemo[89821:6278825] 當(dāng)前線程:<NSThread: 0x6000004744c0>{number = 4, name = (null)},解鎖
pthread_mutex(recursive) 遞歸鎖
遞歸鎖最大的特點(diǎn)就是允許同一個(gè)線程在未釋放其擁有的鎖時(shí)反復(fù)對(duì)該鎖進(jìn)行加鎖操作。而之前介紹的幾種鎖可以看到,加鎖后只能有一個(gè)線程訪問(wèn)該對(duì)象,后面的線程需要排隊(duì),并且lock和unlock都是對(duì)應(yīng)出現(xiàn)的。
下面是代碼:
- (void)setPthreadMutexRecursive
{
static pthread_mutex_t pLock;
pthread_mutexattr_t attr;
//初始化attr并且給它賦予默認(rèn)
pthread_mutexattr_init(&attr);
//設(shè)置鎖類型,這邊是設(shè)置為遞歸鎖
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&pLock, &attr);
//銷毀一個(gè)屬性對(duì)象,在重新進(jìn)行初始化之前該結(jié)構(gòu)不能重新使用
pthread_mutexattr_destroy(&attr);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void (^RecursiveBlock)(int);
RecursiveBlock = ^(int value) {
pthread_mutex_lock(&pLock);
if (value > 0) {
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],value);
RecursiveBlock(value - 1);
}
pthread_mutex_unlock(&pLock);
};
RecursiveBlock(5);
});
}
打印結(jié)果:
2018-04-23 17:34:36.252635+0800 LockDemo[90381:6304880] 當(dāng)前線程:<NSThread: 0x60000046ec00>{number = 3, name = (null)},number=5
2018-04-23 17:34:36.252947+0800 LockDemo[90381:6304880] 當(dāng)前線程:<NSThread: 0x60000046ec00>{number = 3, name = (null)},number=4
2018-04-23 17:34:36.253129+0800 LockDemo[90381:6304880] 當(dāng)前線程:<NSThread: 0x60000046ec00>{number = 3, name = (null)},number=3
2018-04-23 17:34:36.254451+0800 LockDemo[90381:6304880] 當(dāng)前線程:<NSThread: 0x60000046ec00>{number = 3, name = (null)},number=2
2018-04-23 17:34:36.254692+0800 LockDemo[90381:6304880] 當(dāng)前線程:<NSThread: 0x60000046ec00>{number = 3, name = (null)},number=1
NSLock
NSLock看名字就會(huì)熟悉一些了,我們來(lái)看一下他的API:
lock:上鎖
unlock:解鎖
trylock:能加鎖返回 YES 并執(zhí)行加鎖操作,相當(dāng)于 lock,反之返回 NO。
lockBeforeDate:這個(gè)方法表示會(huì)在傳入的時(shí)間內(nèi)嘗試加鎖,若能加鎖則執(zhí)行加鎖操作并返回 YES,反之返回 NO。
接下來(lái)上代碼:
- (void)setNSLock
{
NSLock *lock = [NSLock new];
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,NSLock上鎖",[NSThread currentThread]);
[lock lock];
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 10;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
NSLog(@"當(dāng)前線程:%@,NSLock解鎖",[NSThread currentThread]);
[lock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,NSLock上鎖",[NSThread currentThread]);
[lock lock];
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 20;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
NSLog(@"當(dāng)前線程:%@,NSLock解鎖",[NSThread currentThread]);
[lock unlock];
});
}
打印結(jié)果:
2018-04-23 17:41:40.355403+0800 LockDemo[90636:6315709] 當(dāng)前線程:<NSThread: 0x604000464340>{number = 4, name = (null)},NSLock上鎖
2018-04-23 17:41:40.355403+0800 LockDemo[90636:6315707] 當(dāng)前線程:<NSThread: 0x604000464400>{number = 3, name = (null)},NSLock上鎖
2018-04-23 17:41:40.355620+0800 LockDemo[90636:6315709] 當(dāng)前線程:<NSThread: 0x604000464340>{number = 4, name = (null)},number=10
2018-04-23 17:41:40.355768+0800 LockDemo[90636:6315709] 當(dāng)前線程:<NSThread: 0x604000464340>{number = 4, name = (null)},number=30
2018-04-23 17:41:40.355913+0800 LockDemo[90636:6315709] 當(dāng)前線程:<NSThread: 0x604000464340>{number = 4, name = (null)},NSLock解鎖
2018-04-23 17:41:40.357151+0800 LockDemo[90636:6315707] 當(dāng)前線程:<NSThread: 0x604000464400>{number = 3, name = (null)},number=30
2018-04-23 17:41:40.357313+0800 LockDemo[90636:6315707] 當(dāng)前線程:<NSThread: 0x604000464400>{number = 3, name = (null)},number=40
2018-04-23 17:41:40.357522+0800 LockDemo[90636:6315707] 當(dāng)前線程:<NSThread: 0x604000464400>{number = 3, name = (null)},NSLock解鎖
NSCondition
這個(gè)方法和信號(hào)量有點(diǎn)相似:
wait:進(jìn)入等待狀態(tài)
waitUntilDate::讓一個(gè)線程等待一定的時(shí)間
signal:?jiǎn)拘岩粋€(gè)等待的線程
broadcast:?jiǎn)拘阉械却木€程
### 線程延遲執(zhí)行
上代碼:
- (void)setNSConditionUntilDate
{
NSCondition *conditionLock = [NSCondition new];
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,NSCondition上鎖",[NSThread currentThread]);
[conditionLock lock];
[conditionLock waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
number = number + 1;
NSLog(@"number=%ld",number);
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
[conditionLock unlock];
});
}
可以看到打印代碼中number=11的代碼在第一次輸出的3s之后。
2018-04-24 10:13:22.892167+0800 LockDemo[92613:6424100] 當(dāng)前線程:<NSThread: 0x600000277300>{number = 3, name = (null)},NSCondition上鎖
2018-04-24 10:13:25.895626+0800 LockDemo[92613:6424100] number=11
2018-04-24 10:13:25.896116+0800 LockDemo[92613:6424100] 當(dāng)前線程:<NSThread: 0x600000277300>{number = 3, name = (null)},number=11
喚醒等待線程
上代碼:
- (void)setNSConditionWait
{
NSCondition *conditionLock = [NSCondition new];
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,NSCondition上鎖",[NSThread currentThread]);
[conditionLock lock];
[conditionLock wait];
number = number + 10;
NSLog(@"number=%ld",number);
[conditionLock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,NSCondition上鎖",[NSThread currentThread]);
[conditionLock lock];
[conditionLock wait];
number = number + 20;
NSLog(@"number=%ld",number);
[conditionLock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
NSLog(@"當(dāng)前線程:%@,NSCondition喚醒等待的線程",[NSThread currentThread]);
[conditionLock signal];
});
}
打印結(jié)果:
2018-04-24 10:21:48.119910+0800 LockDemo[92914:6437121] 當(dāng)前線程:<NSThread: 0x604000466d00>{number = 4, name = (null)},NSCondition上鎖
2018-04-24 10:21:48.119911+0800 LockDemo[92914:6437122] 當(dāng)前線程:<NSThread: 0x604000466dc0>{number = 3, name = (null)},NSCondition上鎖
2018-04-24 10:21:50.121817+0800 LockDemo[92914:6437120] 當(dāng)前線程:<NSThread: 0x6000002764c0>{number = 5, name = (null)},NSCondition喚醒等待的線程
2018-04-24 10:21:50.122050+0800 LockDemo[92914:6437121] number=30
喚醒所有等待線程
- (void)setNSConditionBroadcast
{
NSCondition *conditionLock = [NSCondition new];
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,NSCondition上鎖",[NSThread currentThread]);
[conditionLock lock];
[conditionLock wait];
number = number + 10;
NSLog(@"number=%ld",number);
[conditionLock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"當(dāng)前線程:%@,NSCondition上鎖",[NSThread currentThread]);
[conditionLock lock];
[conditionLock wait];
number = number + 20;
NSLog(@"number=%ld",number);
[conditionLock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
NSLog(@"當(dāng)前線程:%@,NSCondition喚醒所有等待的線程",[NSThread currentThread]);
[conditionLock broadcast];
});
}
打印結(jié)果:
2018-04-24 10:23:26.901406+0800 LockDemo[92991:6440383] 當(dāng)前線程:<NSThread: 0x600000277480>{number = 3, name = (null)},NSCondition上鎖
2018-04-24 10:23:26.901406+0800 LockDemo[92991:6440385] 當(dāng)前線程:<NSThread: 0x60400026d7c0>{number = 4, name = (null)},NSCondition上鎖
2018-04-24 10:23:28.904168+0800 LockDemo[92991:6440386] 當(dāng)前線程:<NSThread: 0x60400026df40>{number = 5, name = (null)},NSCondition喚醒所有等待的線程
2018-04-24 10:23:28.904544+0800 LockDemo[92991:6440383] number=20
2018-04-24 10:23:28.904763+0800 LockDemo[92991:6440385] number=40
@synchronized 條件鎖
@synchronized 應(yīng)該是一種比較簡(jiǎn)單的鎖。
直接上代碼:
- (void)setSynchronized
{
__block NSInteger number = 10;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self)
{
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 10;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
}
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self)
{
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
number += 20;
NSLog(@"當(dāng)前線程:%@,number=%ld",[NSThread currentThread],number);
}
});
}
打印結(jié)果:
2018-04-24 10:29:48.814631+0800 LockDemo[93300:6451071] 當(dāng)前線程:<NSThread: 0x600000467900>{number = 3, name = (null)},number=10
2018-04-24 10:29:48.815056+0800 LockDemo[93300:6451071] 當(dāng)前線程:<NSThread: 0x600000467900>{number = 3, name = (null)},number=20
2018-04-24 10:29:48.815291+0800 LockDemo[93300:6451070] 當(dāng)前線程:<NSThread: 0x600000468000>{number = 4, name = (null)},number=20
2018-04-24 10:29:48.816572+0800 LockDemo[93300:6451070] 當(dāng)前線程:<NSThread: 0x600000468000>{number = 4, name = (null)},number=40
NSConditionLock 條件鎖
這個(gè)鎖和NSLock相差不大,多了一個(gè)condition參數(shù),可以理解為一個(gè)條件標(biāo)示。也可以實(shí)現(xiàn)任務(wù)之前的互相依賴。
放代碼:
- (void)setConditionLock
{
NSConditionLock *condationLock = [[NSConditionLock alloc] init];
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if([condationLock tryLockWhenCondition:0]){
NSLog(@"線程1");
[condationLock unlockWithCondition:1];
}else{
NSLog(@"失敗");
}
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[condationLock lockWhenCondition:3];
NSLog(@"線程2");
[condationLock unlockWithCondition:2];
});
//線程3
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[condationLock lockWhenCondition:1];
NSLog(@"線程3");
[condationLock unlockWithCondition:3];
});
}
打印結(jié)果:
2018-04-24 10:46:04.325347+0800 LockDemo[93661:6468125] 線程1
2018-04-24 10:46:04.325573+0800 LockDemo[93661:6468124] 線程3
2018-04-24 10:46:04.325775+0800 LockDemo[93661:6468122] 線程2
由上可知,我們?cè)诔跏蓟?NSConditionLock 對(duì)象時(shí),給了他的標(biāo)示為 0;執(zhí)行 tryLockWhenCondition:時(shí),我們傳入的條件標(biāo)示也是 0,所 以線程1 加鎖成功;執(zhí)行 unlockWithCondition:時(shí),這時(shí)候會(huì)把condition由 0 修改為 1;因?yàn)閏ondition 修改為了 1, 會(huì)先走到 線程3,然后 線程3 又將 condition 修改為 3,最后走了線程2 的流程。
最后
以上就是全部的內(nèi)容,還是放一個(gè)demo在這里吧。