IOS多執行緒程式設計之鎖的理解

2022-08-09 17:15:12 字數 2752 閱讀 7962

一、需要互斥的例子

在多執行緒環境中,無論哪個函式方法都可以在多執行緒中同時執行。但是,在使用共享變數時,或者在執行檔案輸出或者繪製圖等的情況下,多執行緒同時執行就可能得到奇怪的結果。

例如,使用整數全域性變數totalnumber來累加處理的資料的個數,為了執行下面的加法計算,在多執行緒環境中執行該方法會得到什麼結果呢?

- (void)addnumber:(nsinteger)n

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

二、鎖

為了使多個執行緒間可以相互排斥地使用全域性變數等共享資源,可以使用nslock類。

鎖具有每次只允許單個執行緒獲得並使用的性質。獲得鎖稱為「加鎖」,釋放鎖稱為」解鎖「。

鎖使用類方法alloc和初始化器init來建立並初始化。但是,鎖應該在程式開始多執行緒執行前建立。

nslock * countlock = [[nslock alloc]init];

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

-  (void) lock;//如果鎖正被使用,則執行緒進入休眠狀態;如果鎖沒被使用,則鎖的狀態變為正被使用,執行緒繼續執行。

- (void) unlock;//將鎖設定為沒被使用,此時如果有等待該鎖資源的正在休眠的執行緒,則將其喚醒。

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

- (void)addnumber:(nsinteger)n

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

多執行緒程式設計之讀寫鎖

讀寫問題是乙個經典的同步問題,主要針對保護很少更新的資料結構這種同步情況。假設有乙個用於儲存dns條目快取的表,它用來將網域名稱解析為相應的ip位址。通常,乙個給定的dns條目將在很長一段時間裡保持不變 在許多情況下,dns條目會保持數年不變。雖然隨著使用者訪問不同的 新的條目可能會被不時地新增到表...

多執行緒程式設計之讀寫鎖

多執行緒程式設計之讀寫鎖 pthread是 posix threads 的簡稱,是posix的執行緒標準。pthread讀寫鎖把對共享資源的訪問者分為讀者和寫者,讀者只對共享資源進行讀訪問,寫者只對共享資源進行寫操作。在互斥機制,讀者和寫者都需要獨立獨佔互斥量以獨佔共享資源,在讀寫鎖機制下,允許同時...

ios 多執行緒之四 執行緒鎖

假如我們在功能的實現過程中,類中有乙個全域性變數,我們建立了多個執行緒去同時改變或者使用這個變數,會出現什麼問題?執行緒鎖就是用來解決多執行緒之間對資源共享的問題 在上文 多執行緒之三 的基礎之上進行演示,模仿多個地點進行售票的案例。1 建立按鈕 問題 當多個執行緒執行某一塊相同 需要執行緒鎖進行保...