你好,歡迎來到IOS教程網

 Ios教程網 >> IOS使用技巧 >> IOS技巧綜合 >> iOS多線程編程之鎖的理解

iOS多線程編程之鎖的理解

編輯:IOS技巧綜合
[摘要]本文是對iOS多線程編程之鎖的理解的講解,對學習IOS蘋果軟件開發有所幫助,與大家分享。

一、需要互斥的例子

在多線程環境中,無論哪個函數方法都可以在多線程中同時執行。但是,在使用共享變量時,或者在執行文件輸出或者繪制圖等的情況下,多線程同時執行就可能得到奇怪的結果。
例如,使用整數全局變量totalNumber來累加處理的數據的個數,為了執行下面的加法計算,在多線程環境中執行該方法會得到什麼結果呢?

- (void)addNumber:(NSInteger)n
{
    totalNumber +=n;
}

當兩個線程同時執行的情況下,當然,在OS功能支持下,線程在運行的過程中會時而得到CPU的執行權,時而被掛起執行權,因此整體上看,執行結果會偏離了我們期待的結果,原因是值的讀取、更新、寫入操作被多線程同時執行了。

二、鎖

為了使多個線程間可以相互排斥地使用全局變量等共享資源,可以使用NSLock類。
鎖具有每次只允許單個線程獲得並使用的性質。獲得鎖稱為“加鎖”,釋放鎖稱為”解鎖“。
鎖使用類方法alloc和初始化器init來創建並初始化。但是,鎖應該在程序開始多線程執行前創建。

NSLock * countLock = [[NSLock alloc]init];

獲得鎖的方法和釋放鎖的方法都在協議NSLocking中定義。

-  (void) lock;//如果鎖正被使用,則線程進入休眠狀態;如果鎖沒被使用,則鎖的狀態變為正被使用,線程繼續執行。
-  (void) unlock;//將鎖設置為沒被使用,此時如果有等待該鎖資源的正在休眠的線程,則將其喚醒。

在該代碼中,從某線程執行1取得鎖到該線程執行2釋放鎖期間,其他線程在執行1時將進入休眠狀態,不能執行臨界區代碼。鎖被釋放後,在執行1時在休眠的線程中選擇一個線程,在該線程取得鎖後進入臨界區執行。

- (void)addNumber:(NSInteger)n
{
  [aLock lock];-----------------------1
  totalNumber +=n;          //臨界區
  [aLock unlock];--------------------2
}

某個鎖被lock後,必須執行一次unlock。而且lock和unlock必須在同一個線程執行。

三、死鎖

線程和鎖的關系必須在設計之初就經過仔細的考慮。如果錯誤地使用鎖,不但不能按照預期執行互斥,還可能使多個線程陷入到不能執行的狀態,即死鎖(deadlock)狀態。


線程1
線程2


線程1占有文件A並正在處理,途中有需要占有文件B。而另一方面,線程2占有文件B,途中有需要占有文件A。線程1為了處理文 件B想要獲得鎖bLock,但是它已經被線程2獲得。同樣,線程2想要獲得的鎖aLock也被線程1占有著。這種情況下,線程1和線程2就會同時進入休眠 狀態,而且雙方都不能跳出該狀態。

四、嘗試獲得鎖

NSLock類不僅能獲得鎖和釋放鎖,還有檢查是否獲得鎖的功能。利用這些功能,就可以在不能獲得鎖時進行其他處理。

-  (BOOL) tryLock

用接收器嘗試獲得某個鎖,如果可以獲得該鎖則返回YES,不能獲得時,與lock處理不同,線程沒有進入休眠狀態,而且直接返回NO並繼續執行。

五、條件鎖

NSConditionLock實例初始化,設置參數condition指定的值。NSConditionLock的指定初始化器。

- (instancetype)initWithCondition:(NSInteger)condition

此時返回鎖中設定的值

@property (readonly) NSInteger condition;

如果鎖正在被使用,則線程進入休眠狀態。
鎖不在被使用時,如果鎖值和參數condition的值一致,則將鎖的狀態改為正在被使用,然後繼續執行,如果不一致,則線程進入休眠狀態。

- (void)lockWhenCondition:(NSInteger)condition;

在鎖中設置參數condition指定的值。將鎖設置為不在使用,此時如果有等待獲得該鎖且處於休眠狀態的線程,則將其喚醒。

- (void)unlockWithCondition:(NSInteger)condition;

尚未使用鎖且鎖值與參數condition相同時,獲得鎖並返回YES,不能獲得鎖時也不進入休眠狀態,而是返回NO,線程繼續執行。

- (BOOL)tryLockWhenCondition:(NSInteger)condition;

使用方法lock、unlock、trylock時都可以獲得鎖和釋放鎖,而且不用關心鎖的值。

六、NSRecursiveLock,遞歸鎖

某線程獲得鎖後,到該線程釋放鎖期間,想要獲得該鎖的線程就會進入休眠。使用NSLock的鎖時,如果已經獲得鎖的線程在沒有釋放它的情況下還想再次獲得該鎖,該線程也會進入休眠。但是,由於沒有從休眠狀態喚醒的線程,所以這就是死鎖。

[aLock lock];
[aLock lock];//這裡發生死鎖
[aLock unlock];
[aLock unlock];

解決這種情況可以使用NSRecursiveLock類的鎖,擁有鎖的線程即使多次獲得同一個鎖也不會進入死鎖。但是,其他線程當然也不能獲得該鎖。獲得次數和釋放次數一致時,鎖就會被釋放。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved