iOS多線程編程之鎖的理解,ios多線程編程

來源:互聯網
上載者:User

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.png
線程2.png


線程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類的鎖,擁有鎖的線程即使多次獲得同一個鎖也不會進入死結。但是,其他線程當然也不能獲得該鎖。獲得次數和釋放次數一致時,鎖就會被釋放。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.