要用到多線程 ,就不得不考慮,線程之間的交互,線程是否安全安全
推薦一個原文連接 是關於 線程鎖的基本使用的 http://blog.csdn.net/qq_30513483/article/details/52349968
這篇博客,也主要引用 這個連接的內容多線程
4.1 OSSpinLock 自旋鎖 :併發
線程經過busy-wait-loop的方式來獲取鎖,任時刻只有一個線程可以得到鎖,其餘線程忙等待直到得到鎖。異步
spinlock在多處理器多線程環境的場景中有很普遍的使用,通常要求使用spinlock的臨界區儘可能簡短,這樣獲取的鎖能夠儘快釋放,以知足其餘忙等的線程。async
Spinlock和mutex不一樣,spinlock不會致使線程的狀態切換(用戶態->內核態),可是spinlock使用不當(如臨界區執行時間過長)會致使cpu busy飆高。函數
/*oop
OS_SPINLOCK_INIT: 默認值爲
0
,在locked
狀態時就會大於0
,unlocked
狀態下爲0
OSSpinLockLock(&oslock):上鎖,參數爲OSSpinLock
地址
OSSpinLockUnlock(&oslock):解鎖,參數爲OSSpinLock
地址
OSSpinLockTry(&oslock):嘗試加鎖,能夠加鎖則當即加鎖並返回YES
,反之返回NO
spa
這裏順便提一下trylock
和lock
使用場景:.net
當前線程鎖失敗,也能夠繼續其它任務,用 trylock 合適
當前線程只有鎖成功後,纔會作一些有意義的工做,那就 lock,不必輪詢 trylock線程
*/
使用:::導入 #import <libkern/OSAtomic.h> iOS 10.0 後被取消 ,須要更換這個鎖
- (void)osspinLock{
__block OSSpinLock oslock = OS_SPINLOCK_INIT;
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"線程1 準備上鎖 %@",[NSThread currentThread]);
OSSpinLockLock(&oslock);
sleep(4);
NSLog(@"線程1 代碼執行 %@",[NSThread currentThread]);
OSSpinLockUnlock(&oslock);
NSLog(@"線程1 解鎖成功 %@",[NSThread currentThread]);
NSLog(@"--------------------------------------------------------");
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"線程2 準備上鎖 %@",[NSThread currentThread]);
OSSpinLockLock(&oslock);
NSLog(@"線程2 代碼執行 %@",[NSThread currentThread]);
OSSpinLockUnlock(&oslock);
NSLog(@"線程2 解鎖成功 %@",[NSThread currentThread]);
}); }
執行結果:::
2017-12-21 15:24:11.495148+0800 DeadThread[12619:4480008] 線程1 準備上鎖 <NSThread: 0x608000071940>{number = 3, name = (null)}
2017-12-21 15:24:11.495148+0800 DeadThread[12619:4480007] 線程2 準備上鎖 <NSThread: 0x60c000261180>{number = 4, name = (null)}
2017-12-21 15:24:11.495376+0800 DeadThread[12619:4480007] 線程2 代碼執行 <NSThread: 0x60c000261180>{number = 4, name = (null)}
2017-12-21 15:24:11.495470+0800 DeadThread[12619:4480007] 線程2 解鎖成功 <NSThread: 0x60c000261180>{number = 4, name = (null)}
2017-12-21 15:24:15.498949+0800 DeadThread[12619:4480008] 線程1 代碼執行 <NSThread: 0x608000071940>{number = 3, name = (null)}
2017-12-21 15:24:15.499124+0800 DeadThread[12619:4480008] 線程1 解鎖成功 <NSThread: 0x608000071940>{number = 3, name = (null)}
2017-12-21 15:24:15.499216+0800 DeadThread[12619:4480008] --------------------------------------------------------
總結結果:::
1.兩個任務都要 異步 + 併發:因此會從新開啓兩個子線程;
2.兩個線程都有鎖:當鎖定後,會執行完這個任務,纔會執行下一個任務;
3.這個結果 只是一中狀況,異步併發 會先發起哪一個任務是不定的;
對上面的代碼稍做修改:::: 給 解鎖的代碼 添加註釋
- (void)osspinLock{ __block OSSpinLock oslock = OS_SPINLOCK_INIT; //線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"線程1 準備上鎖 %@",[NSThread currentThread]); OSSpinLockLock(&oslock); sleep(4); NSLog(@"線程1 代碼執行 %@",[NSThread currentThread]); // OSSpinLockUnlock(&oslock); NSLog(@"線程1 解鎖成功 %@",[NSThread currentThread]); NSLog(@"--------------------------------------------------------"); }); //線程2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"線程2 準備上鎖 %@",[NSThread currentThread]); OSSpinLockLock(&oslock); NSLog(@"線程2 代碼執行 %@",[NSThread currentThread]); // OSSpinLockUnlock(&oslock); NSLog(@"線程2 解鎖成功 %@",[NSThread currentThread]); }); }
執行結果::::
2017-12-21 15:29:34.099561+0800 DeadThread[12653:4494849] 線程1 準備上鎖 <NSThread: 0x60c000262100>{number = 3, name = (null)} 2017-12-21 15:29:34.099561+0800 DeadThread[12653:4494848] 線程2 準備上鎖 <NSThread: 0x60000047bf00>{number = 4, name = (null)} 2017-12-21 15:29:38.100529+0800 DeadThread[12653:4494849] 線程1 代碼執行 <NSThread: 0x60c000262100>{number = 3, name = (null)} 2017-12-21 15:29:38.100739+0800 DeadThread[12653:4494849] 線程1 解鎖成功 <NSThread: 0x60c000262100>{number = 3, name = (null)} 2017-12-21 15:29:38.100880+0800 DeadThread[12653:4494849] --------------------------------------------------------
總結結果:::
1.兩個任務,每一個都含有鎖:當有個任務先獲得執行的時候,任務執行完沒有了解鎖的過程
可是另外一個任務,會一直等待 鎖解除才能執行, 始終不會執行……
4.2 pthread_mutex 互斥鎖 ::
使用::#import <pthread.h>
/**
pthread_mutex 中也有個pthread_mutex_trylock(&pLock),
和上面提到的 OSSpinLockTry(&oslock)
區別在於,前者能夠加鎖時返回的是 0,不然返回一個錯誤提示碼;
後者返回的 YES和NO
*/
-(void)mutexLock{ static pthread_mutex_t pLock; pthread_mutex_init(&pLock, NULL); //1.線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"線程1 準備上鎖 %@",[NSThread currentThread]); pthread_mutex_lock(&pLock); sleep(3); NSLog(@"線程1 執行 %@",[NSThread currentThread]); pthread_mutex_unlock(&pLock); NSLog(@"線程1 成功解鎖 %@",[NSThread currentThread]); }); //1.線程2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"線程2 準備上鎖 %@",[NSThread currentThread]); pthread_mutex_lock(&pLock); sleep(3); NSLog(@"線程2 執行 %@",[NSThread currentThread]); pthread_mutex_unlock(&pLock); NSLog(@"線程2 成功解鎖 %@",[NSThread currentThread]); }); }
執行結果:::
2017-12-21 15:37:37.219816+0800 DeadThread[12685:4529083] 線程2 準備上鎖 <NSThread: 0x60000006c980>{number = 4, name = (null)} 2017-12-21 15:37:37.219816+0800 DeadThread[12685:4529086] 線程1 準備上鎖 <NSThread: 0x604000469880>{number = 3, name = (null)} 2017-12-21 15:37:40.223145+0800 DeadThread[12685:4529083] 線程2 執行 <NSThread: 0x60000006c980>{number = 4, name = (null)} 2017-12-21 15:37:40.223404+0800 DeadThread[12685:4529083] 線程2 成功解鎖 <NSThread: 0x60000006c980>{number = 4, name = (null)} 2017-12-21 15:37:43.226685+0800 DeadThread[12685:4529086] 線程1 執行 <NSThread: 0x604000469880>{number = 3, name = (null)} 2017-12-21 15:37:43.226809+0800 DeadThread[12685:4529086] 線程1 成功解鎖 <NSThread: 0x604000469880>{number = 3, name = (null)}
結果分析:::
1.異步 + 併發 -> 兩個線程;
2.先加鎖的任務 先完成,等待任務完成解鎖,在完成下一個任務;
4.3 pthread_mutex(recursive) 遞歸鎖
/**
通過上面幾種例子,咱們能夠發現:
加鎖後只能有一個線程訪問該對象,後面的線程須要排隊,
而且 lock 和 unlock 是對應出現的,同一線程屢次 lock 是不容許的,
而遞歸鎖容許同一個線程在未釋放其擁有的鎖時反覆對該鎖進行加鎖操做。
上面的代碼若是咱們用 pthread_mutex_init(&pLock, NULL) 初始化會出現死鎖的狀況,遞歸鎖能很好的避免這種狀況的死鎖;
*/
-(void)recursiveLock{ static pthread_mutex_t pLock; pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); //初始化attr而且給它賦予默認 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); //設置鎖類型,這邊是設置爲遞歸鎖 pthread_mutex_init(&pLock, &attr); pthread_mutexattr_destroy(&attr); //銷燬一個屬性對象,在從新進行初始化以前該結構不能從新使用 static void (^RecursiveBlock)(int); //1.線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ RecursiveBlock = ^(int value) { pthread_mutex_lock(&pLock); if (value > 0) { NSLog(@"value: %d", value); RecursiveBlock(value - 1); } pthread_mutex_unlock(&pLock); }; RecursiveBlock(5); }); }
執行結果:::
2017-12-21 15:45:39.095417+0800 DeadThread[12721:4562499] value: 5 2017-12-21 15:45:39.095583+0800 DeadThread[12721:4562499] value: 4 2017-12-21 15:45:39.096599+0800 DeadThread[12721:4562499] value: 3 2017-12-21 15:45:39.097190+0800 DeadThread[12721:4562499] value: 2 2017-12-21 15:45:39.097645+0800 DeadThread[12721:4562499] value: 1
結果分析:::
1.開啓新的線程;
2.遞歸鎖 ->容許同一個線程在未釋放其擁有的鎖時反覆對該鎖進行加鎖操做;
4.4 dispatch_semaphore 信號量
/**
dispatch_semaphore_create(1): 傳入值必須
>=0
, 若傳入爲0
則阻塞線程並等待timeout,時間到後會執行其後的語句
dispatch_semaphore_wait(signal, overTime):能夠理解爲lock
,會使得signal
值-1
dispatch_semaphore_signal(signal):能夠理解爲unlock
,會使得signal
值+1
*/
-(void)GCDSemaphore{ dispatch_semaphore_t signal = dispatch_semaphore_create(1); //傳入值必須 >=0, 若傳入爲0則阻塞線程並等待timeout,時間到後會執行其後的語句 dispatch_time_t overTime = dispatch_time(DISPATCH_TIME_NOW, 3.0f * NSEC_PER_SEC); //線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"線程1 等待ing %@",[NSThread currentThread]); dispatch_semaphore_wait(signal, overTime); //signal 值 -1 sleep(4); NSLog(@"線程1 執行 %@",[NSThread currentThread]); dispatch_semaphore_signal(signal); //signal 值 +1 NSLog(@"線程1 發送信號 %@",[NSThread currentThread]); NSLog(@"--------------------------------------------------------"); }); //線程2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"線程2 等待ing %@",[NSThread currentThread]); dispatch_semaphore_wait(signal, overTime); sleep(4); NSLog(@"線程2 執行 %@",[NSThread currentThread]); dispatch_semaphore_signal(signal); NSLog(@"線程2 發送信號 %@",[NSThread currentThread]); }); }
執行結果:::
2017-12-21 15:49:55.355078+0800 DeadThread[12761:4592703] 線程1 等待ing <NSThread: 0x60c000076400>{number = 3, name = (null)} 2017-12-21 15:49:55.355079+0800 DeadThread[12761:4592705] 線程2 等待ing <NSThread: 0x60c00007d740>{number = 5, name = (null)} 2017-12-21 15:49:59.360317+0800 DeadThread[12761:4592703] 線程1 執行 <NSThread: 0x60c000076400>{number = 3, name = (null)} 2017-12-21 15:49:59.360482+0800 DeadThread[12761:4592703] 線程1 發送信號 <NSThread: 0x60c000076400>{number = 3, name = (null)} 2017-12-21 15:49:59.360568+0800 DeadThread[12761:4592703] -------------------------------------------------------- 2017-12-21 15:50:02.358932+0800 DeadThread[12761:4592705] 線程2 執行 <NSThread: 0x60c00007d740>{number = 5, name = (null)} 2017-12-21 15:50:02.359109+0800 DeadThread[12761:4592705] 線程2 發送信號 <NSThread: 0x60c00007d740>{number = 5, name = (null)}
結果分析:::
1.初始信號量大於0
能夠發現,由於咱們初始化信號量的時候是大於 0
的,因此並無阻塞線程,而是直接執行了 線程1 線程2。
把信號量設置爲 0 修改上面代碼
dispatch_semaphore_t signal = dispatch_semaphore_create(0);
執行結果::::
2017-12-21 15:53:43.545606+0800 DeadThread[12804:4615777] 線程2 等待ing <NSThread: 0x604000076880>{number = 4, name = (null)} 2017-12-21 15:53:43.545651+0800 DeadThread[12804:4615776] 線程1 等待ing <NSThread: 0x60000026cbc0>{number = 5, name = (null)} 2017-12-21 15:53:50.553973+0800 DeadThread[12804:4615777] 線程2 執行 <NSThread: 0x604000076880>{number = 4, name = (null)} 2017-12-21 15:53:50.553973+0800 DeadThread[12804:4615776] 線程1 執行 <NSThread: 0x60000026cbc0>{number = 5, name = (null)} 2017-12-21 15:53:50.554140+0800 DeadThread[12804:4615777] 線程2 發送信號 <NSThread: 0x604000076880>{number = 4, name = (null)} 2017-12-21 15:53:50.554144+0800 DeadThread[12804:4615776] 線程1 發送信號 <NSThread: 0x60000026cbc0>{number = 5, name = (null)} 2017-12-21 15:53:50.554252+0800 DeadThread[12804:4615776] --------------------------------------------------------
結果分析:::
overTime
生效了。
關於信號量,咱們能夠用停車來比喻: 停車場剩餘4個車位,那麼即便同時來了四輛車也能停的下。若是此時來了五輛車,那麼就有一輛須要等待。 信號量的值(signal)就至關於剩餘車位的數目,dispatch_semaphore_wait 函數就至關於來了一輛車,dispatch_semaphore_signal 就至關於走了一輛車。
停車位的剩餘數目在初始化的時候就已經指明瞭(dispatch_semaphore_create(long value)),調用一次 dispatch_semaphore_signal,剩餘的車位就增長一個;
調用一次dispatch_semaphore_wait 剩餘車位就減小一個;當剩餘車位爲 0 時,再來車(即調用 dispatch_semaphore_wait)就只能等待。
有可能同時有幾輛車等待一個停車位。有些車主沒有耐心,給本身設定了一段等待時間,這段時間內等不到停車位就走了,若是等到了就開進去停車。
而有些車主就像把車停在這,因此就一直等下去。
4.5 nslock 普通鎖
/**
lock、unlock:很少作解釋,和上面同樣
trylock:能加鎖返回 YES 並執行加鎖操做,至關於 lock,反之返回 NO
lockBeforeDate:這個方法表示會在傳入的時間內嘗試加鎖,若能加鎖則執行加鎖操做並返回 YES,反之返回 NO
*/
- (void)nslock{ NSLock *lock = [NSLock new]; //線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"線程1 嘗試加速ing..."); [lock lock]; sleep(5);// 能夠設置 3 和下面的等待 4 進行比交 NSLog(@"線程1 執行"); [lock unlock]; NSLog(@"線程1 解鎖成功"); }); //線程2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"線程2 嘗試加速ing..."); BOOL x = [lock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:4]]; if (x) { NSLog(@"線程2 執行"); [lock unlock]; }else{ NSLog(@"失敗"); } // [lock lock]; // NSLog(@"線程2 執行"); // [lock unlock]; // NSLog(@"線程2 解鎖成功"); });
執行結果:::
2017-12-21 15:57:18.176823+0800 DeadThread[12833:4641424] 線程2 嘗試加速ing... 2017-12-21 15:57:18.176823+0800 DeadThread[12833:4641448] 線程1 嘗試加速ing... 2017-12-21 15:57:22.179919+0800 DeadThread[12833:4641424] 失敗 2017-12-21 15:57:23.180686+0800 DeadThread[12833:4641448] 線程1 執行 2017-12-21 15:57:23.180876+0800 DeadThread[12833:4641448] 線程1 解鎖成功
結果分析:::
1. 在4s 內,加鎖是失敗的;
4.6 NSRecursiveLock 遞歸鎖
/**
遞歸鎖能夠被同一線程屢次請求,而不會引發死鎖。這主要是用在循環或遞歸操做中。
- (BOOL)tryLock;
- (BOOL)lockBeforeDate:(NSDate *)limit;
*/
-(void)nsrecursiveLock{ NSRecursiveLock *rLock = [NSRecursiveLock new]; // NSLock *rLock = [NSLock new]; 換用這個 形成死鎖 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ static void (^RecursiveBlock)(int); RecursiveBlock = ^(int value) { [rLock lock]; if (value > 0) { NSLog(@"線程%d", value); RecursiveBlock(value - 1); } [rLock unlock]; }; RecursiveBlock(4); }); }
執行結果:::
2017-12-21 16:02:15.559443+0800 DeadThread[12860:4670051] 線程4 2017-12-21 16:02:15.559602+0800 DeadThread[12860:4670051] 線程3 2017-12-21 16:02:15.559712+0800 DeadThread[12860:4670051] 線程2 2017-12-21 16:02:15.559929+0800 DeadThread[12860:4670051] 線程1
結果分析:::
1.相似於 4.2的遞歸鎖;
4.6 @synchronized 條件鎖
-(void)synchronized{ //線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @synchronized (self) { NSLog(@"線程1加鎖成功 %@",[NSThread currentThread]); sleep(2); NSLog(@"線程1"); } }); //線程2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @synchronized (self) { NSLog(@"線程2加鎖成功 %@",[NSThread currentThread]); NSLog(@"線程2"); } }); }
執行結果:::
2017-12-21 16:04:22.076568+0800 DeadThread[12887:4680292] 線程1加鎖成功 <NSThread: 0x60000006fa00>{number = 5, name = (null)} 2017-12-21 16:04:24.077240+0800 DeadThread[12887:4680292] 線程1 2017-12-21 16:04:24.077530+0800 DeadThread[12887:4680295] 線程2加鎖成功 <NSThread: 0x60400027d840>{number = 4, name = (null)} 2017-12-21 16:04:24.077611+0800 DeadThread[12887:4680295] 線程2
結果分析:::
1.@synchronized(obj),保護這個對象,至關於 NSLock 鎖定了 obj 同樣;
4.7 //NSCondition 條件鎖
/**
wait:進入等待狀態
waitUntilDate::讓一個線程等待必定的時間
signal:喚醒一個等待的線程
broadcast:喚醒全部等待的線程
*/
-(void)conditionLockOne{ NSCondition *cLock = [NSCondition new]; //線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"start %@",[NSThread currentThread]); [cLock lock]; [cLock waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]]; NSLog(@"線程1 執行 %@",[NSThread currentThread]); [cLock unlock]; NSLog(@"end %@",[NSThread currentThread]); }); }
執行結果:::
2017-12-21 16:16:14.096649+0800 DeadThread[12936:4727712] start <NSThread: 0x60800026fb80>{number = 3, name = (null)}
2017-12-21 16:16:16.100037+0800 DeadThread[12936:4727712] 線程1 執行 <NSThread: 0x60800026fb80>{number = 3, name = (null)}
2017-12-21 16:16:16.100296+0800 DeadThread[12936:4727712] end <NSThread: 0x60800026fb80>{number = 3, name = (null)}
結果分析:::
1.condition 能夠像 nslock 樣使用
-(void)conditionLockTwo{ NSCondition *cLock = [NSCondition new]; //線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [cLock lock]; NSLog(@"線程1加鎖成功 %@",[NSThread currentThread]); [cLock wait]; NSLog(@"線程1 %@",[NSThread currentThread]); [cLock unlock]; NSLog(@"線程1 解鎖 %@",[NSThread currentThread]); }); //線程2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [cLock lock]; NSLog(@"線程2加鎖成功 %@",[NSThread currentThread]); [cLock wait]; NSLog(@"線程2 %@",[NSThread currentThread]); [cLock unlock]; NSLog(@"線程2 解鎖 %@",[NSThread currentThread]); }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ sleep(2); NSLog(@"喚醒一個等待的線程 %@",[NSThread currentThread]); [cLock signal]; // [cLock signal]; }); // dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // sleep(2); // NSLog(@"喚醒全部等待的線程 %@",[NSThread currentThread]); // [cLock broadcast]; // }); }
執行結果:::
2017-12-21 16:18:01.779627+0800 DeadThread[12957:4738568] 線程1加鎖成功 <NSThread: 0x600000464d00>{number = 5, name = (null)} 2017-12-21 16:18:01.780054+0800 DeadThread[12957:4738569] 線程2加鎖成功 <NSThread: 0x60800007b140>{number = 3, name = (null)} 2017-12-21 16:18:03.784645+0800 DeadThread[12957:4738565] 喚醒一個等待的線程 <NSThread: 0x60400007d980>{number = 6, name = (null)} 2017-12-21 16:18:03.784862+0800 DeadThread[12957:4738568] 線程1 <NSThread: 0x600000464d00>{number = 5, name = (null)} 2017-12-21 16:18:03.784948+0800 DeadThread[12957:4738568] 線程1 解鎖 <NSThread: 0x600000464d00>{number = 5, name = (null)}
結果分析:::
1. 能夠 設置wait 屬性,而後執行喚醒命令,喚醒線程,或者喚醒 全部 wait的線程
/**
tryLockWhenCondition:
result
咱們在初始化 NSConditionLock 對象時,給了他的標示爲 0
執行 tryLockWhenCondition:時,咱們傳入的條件標示也是 0,所 以線程1 加鎖成功
執行 unlockWithCondition:時,這時候會把condition由 0 修改成 1
由於condition 修改成了 1, 會先走到 線程3,而後 線程3 又將 condition 修改成 3
最後 走了 線程2 的流程
從上面的結果咱們能夠發現,NSConditionLock 還能夠實現任務之間的依賴。
*/
-(void)conditionLockThree{ NSConditionLock *cLock = [[NSConditionLock alloc] initWithCondition:0]; //線程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if([cLock tryLockWhenCondition:0]){ NSLog(@"線程1"); [cLock unlockWithCondition:1]; }else{ NSLog(@"失敗"); } }); //線程2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [cLock lockWhenCondition:3]; NSLog(@"線程2"); [cLock unlockWithCondition:2]; }); //線程3 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [cLock lockWhenCondition:1]; NSLog(@"線程3"); [cLock unlockWithCondition:3]; }); }
執行結果:::
2017-12-21 16:20:25.387192+0800 DeadThread[12984:4750303] 線程1 2017-12-21 16:20:25.387338+0800 DeadThread[12984:4750301] 線程3 2017-12-21 16:20:25.387430+0800 DeadThread[12984:4750304] 線程2