iOS 多線程的簡單理解(4) 線程鎖的簡單使用

 

要用到多線程 ,就不得不考慮,線程之間的交互,線程是否安全安全

推薦一個原文連接 是關於 線程鎖的基本使用的  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 狀態時就會大於 0unlocked狀態下爲 0
OSSpinLockLock(&oslock):上鎖,參數爲 OSSpinLock 地址
OSSpinLockUnlock(&oslock):解鎖,參數爲 OSSpinLock 地址
OSSpinLockTry(&oslock):嘗試加鎖,能夠加鎖則當即加鎖並返回 YES,反之返回 NOspa

這裏順便提一下trylocklock使用場景:.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] --------------------------------------------------------

 結果分析:::

1. 初始信號量爲0 ;能夠看到這時候咱們設置的 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
相關文章
相關標籤/搜索