自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

NSRecursiveLock遞歸鎖的使用

企業(yè)動(dòng)態(tài)
NSRecursiveLock實(shí)際上定義的是一個(gè)遞歸鎖,這個(gè)鎖可以被同一線程多次請求,而不會(huì)引起死鎖。這主要是用在循環(huán)或遞歸操作中。我們先來看一個(gè)示例:

NSRecursiveLock遞歸鎖的使用

NSRecursiveLock實(shí)際上定義的是一個(gè)遞歸鎖,這個(gè)鎖可以被同一線程多次請求,而不會(huì)引起死鎖。這主要是用在循環(huán)或遞歸操作中。我們先來看一個(gè)示例:

  1. NSLock *lock = [[NSLock alloc] init]; 
  2.  
  3. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
  4.  
  5. static void (^RecursiveMethod)(int); 
  6.  
  7. RecursiveMethod = ^(int value) { 
  8.  
  9. [lock lock]; 
  10. if (value > 0) { 
  11.  
  12. NSLog(@"value = %d", value); 
  13. sleep(2); 
  14. RecursiveMethod(value - 1); 
  15. [lock unlock]; 
  16. }; 
  17.  
  18. RecursiveMethod(5); 
  19. });

這段代碼是一個(gè)典型的死鎖情況。在我們的線程中,RecursiveMethod是遞歸調(diào)用的。所以每次進(jìn)入這個(gè)block時(shí),都會(huì)去加一次鎖,而從第二次開始,由于鎖已經(jīng)被使用了且沒有解鎖,所以它需要等待鎖被解除,這樣就導(dǎo)致了死鎖,線程被阻塞住了。調(diào)試器中會(huì)輸出如下信息:

  1. value = 5 
  2. *** -[NSLock lock]: deadlock (<NSLock: 0x1700ceee0'(null)') *** Break on _NSLockError() to debug.  

在這種情況下,我們就可以使用NSRecursiveLock。它可以允許同一線程多次加鎖,而不會(huì)造成死鎖。遞歸鎖會(huì)跟蹤它被lock的次數(shù)。每次成功的lock都必須平衡調(diào)用unlock操作。只有所有達(dá)到這種平衡,鎖***才能被釋放,以供其它線程使用。

所以,對上面的代碼進(jìn)行一下改造,

NSRecursiveLock *lock = [[NSRecursiveLock alloc] init];

這樣,程序就能正常運(yùn)行了,其輸出如下所示:

  1. value = 5 
  2. value = 4 
  3. value = 3 
  4. value = 2 
  5. value = 1 

NSRecursiveLock除了實(shí)現(xiàn)NSLocking協(xié)議的方法外,還提供了兩個(gè)方法,分別如下:

  1. // 在給定的時(shí)間之前去嘗試請求一個(gè)鎖 
  2. - (BOOL)lockBeforeDate:(NSDate *)limit 
  3.  
  4. // 嘗試去請求一個(gè)鎖,并會(huì)立即返回一個(gè)布爾值,表示嘗試是否成功 
  5. - (BOOL)tryLock 
  6.  
  7. 這兩個(gè)方法都可以用于在多線程的情況下,去嘗試請求一個(gè)遞歸鎖,然后根據(jù)返回的布爾值,來做相應(yīng)的處理。如下代碼所示: 
  8.  
  9. NSRecursiveLock *lock = [[NSRecursiveLock alloc] init]; 
  10.  
  11. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
  12.  
  13. static void (^RecursiveMethod)(int); 
  14.  
  15. RecursiveMethod = ^(int value) { 
  16.  
  17. [lock lock]; 
  18. if (value > 0) { 
  19.  
  20. NSLog(@"value = %d", value); 
  21. sleep(2); 
  22. RecursiveMethod(value - 1); 
  23. [lock unlock]; 
  24. }; 
  25.  
  26. RecursiveMethod(5); 
  27. }); 
  28.  
  29. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
  30.  
  31. sleep(2); 
  32. BOOL flag = [lock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 
  33. if (flag) { 
  34. NSLog(@"lock before date"); 
  35.  
  36. [lock unlock]; 
  37. else { 
  38. NSLog(@"fail to lock before date"); 
  39. });

在前面的代碼中,我們又添加了一段代碼,增加一個(gè)線程來獲取遞歸鎖。我們在第二個(gè)線程中嘗試去獲取遞歸鎖,當(dāng)然這種情況下是會(huì)失敗的,輸出結(jié)果如下:

  1. value = 5 
  2. value = 4 
  3. fail to lock before date 
  4. value = 3 
  5. value = 2 
  6. value = 1 

另外,NSRecursiveLock還聲明了一個(gè)name屬性,如下:

@property(copy) NSString *name

我們可以使用這個(gè)字符串來標(biāo)識一個(gè)鎖。Cocoa也會(huì)使用這個(gè)name作為錯(cuò)誤描述信息的一部分。

 

參考

 

NSRecursiveLock Class Reference

 

責(zé)任編輯:chenqingxiang 來源: 南峰子的技術(shù)博客
相關(guān)推薦

2024-01-29 01:08:01

悲觀鎖遞歸鎖讀寫鎖

2024-08-28 08:00:00

2009-09-02 18:44:19

C#遞歸

2010-09-25 15:20:43

SQL遞歸語句

2013-08-20 09:23:06

Scala遞歸

2024-01-30 07:36:51

Javalocks

2023-01-06 09:40:20

項(xiàng)目性能

2020-07-10 08:15:19

遞歸算法函數(shù)

2009-06-06 19:17:37

java遞歸刪除

2013-04-10 10:58:19

LambdaC#

2023-11-10 16:04:46

遞歸圖Python

2022-06-15 07:32:35

Lock線程Java

2009-08-31 17:11:37

Lambda表達(dá)式

2009-11-17 16:16:59

PHP遞歸函數(shù)

2024-11-29 14:50:45

2024-02-29 09:44:36

Java工具

2018-07-31 10:10:06

MySQLInnoDB死鎖

2010-04-02 15:04:14

Oracle遞歸查詢

2010-01-21 17:31:15

VB.NET遞歸過程

2010-03-05 09:40:08

Python遞歸
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號