iOS多執行緒程式設計 執行緒同步總結

2021-06-06 00:00:36 字數 2976 閱讀 5803

1:原子操作 - osatomic系列函式

ios平台下的原子操作函式都以osatomic開頭,使用時需要包含標頭檔案。不同執行緒如果通過原子操作函式對同一變數進行操作,可以保證乙個執行緒的操作不會影響到其他執行緒內對此變數的操作,因為這些操作都是原子式的。因為原子操作只能對內建型別進行操作,所以原子操作能夠同步的執行緒只能位於同乙個程序的位址空間內。

ios平台下的鎖物件為nslock物件,進入鎖通過呼叫lock函式,解鎖呼叫unlock函式(因為ios中大部分的執行緒同步類都繼承自nslocking協議,所以其加鎖/解鎖的操作基本都為lock/unlock函式),同乙個nslock物件成功呼叫lock函式後,在其顯式unlock之前任何執行緒都不能再對此nslock物件加鎖,以達到互斥訪問的目的。除了lock函式,對nslock加鎖的函式還包括trylock以及lockbeforedate函式,lock函式在成功加鎖之間會一直阻塞,而trylock會嘗試加鎖,如果不成功,不會阻塞,而是直接返回no,lockbeforedate則是阻塞到傳入的nsdate日期為止。

除了nslock,ios還提供了nsrecursive、nsconditionlock型別的鎖型別。nsrecursive與nslock最大的區別就是nsrecursive是可重入的,也就是說乙個執行緒可以對乙個nsrecursive物件多次呼叫lock,只要解鎖時呼叫相同次數的unlock函式便可。nsconditionlock是一種帶有條件的鎖物件,除了基本的lock與unlock函式,還提供了lockwithcondition以及unlockwithcondition,這兩個函式接收整型型別的資料作為引數,只有當乙個unlockwithcondition物件被呼叫時,對應的lockwithcondition才會正常返回。這種機制在需幾多個執行緒順序化的完成某個任務時比較有用,例程如下:

//執行緒a

id condlock = [[nsconditionlock alloc] initwithcondition:no_data];

while(true)

//執行緒b

while (true)

除了顯示的生成nslock系列物件,還可以通過將**放到@synchronized內來達到同步的目的,一段放入其內的**,不同的執行緒是不能重入的例如:

- (void)mymethod:(id)anobj

}

nslock系列物件都是可以具名的,也就是說,這些物件可以用於不同程序內部的執行緒的同步。

3:事件 - nscondtion

nsconditon型別提供了wait與signal函式,分別代表了等待事件的操作以及觸發事件的操作。除了wait函式,nscondition還提供了waituntildate函式,其功能與nslock中的lockbeforedate大致相同,簡要來說就是提供了乙個帶超時的wait函式。

雖然nscondition與windows環境下event型別所完成的功能大致類似,但對乙個熟悉event型別的開發人員來說,nsconditon的行為會有點奇怪:

第一點:因為遵循nslocking協議,所以nscondition在觸發與等待過程的前後要分別呼叫lock與unlock函式,前面提到過,當乙個遵循nslocking協議的物件呼叫lock後,其他的對此物件的lock呼叫都會阻塞。那麼,如果兩個執行緒a和b,a要觸發事件,b接收事件,b執行緒在呼叫lock後,通過呼叫wait函式進入等待事件觸發的狀態,那麼,a執行緒豈不是再也沒有機會對這個事件進行觸發了(因為此物件已經被b執行緒lock)?秘密就在於wait函式的呼叫,其實,在wait函式內部悄悄的呼叫了unlock函式,也就是說在呼叫wati函式後,這個nscondition物件就處於了無鎖的狀態,這樣a執行緒就可以對此物件加鎖並觸發該nscondition物件。當乙個事件被其他執行緒觸發時,在wait函式內部得到此事件被觸發的通知,然後對此事件重新呼叫lock函式,然後函式返回,而在函式外部,看起來好像接收事件的執行緒從來沒有放開nscondition物件的所有權,b執行緒直接由阻塞狀態進入了觸發狀態。

第二點:當有多個執行緒進入阻塞狀態,等待同乙個autoreset的event物件被觸發時,在windows環境下喚醒哪乙個執行緒是沒有固定的順序的,也就是說作業系統對喚醒哪乙個執行緒不會提供任何的保證。而在ios平台上,經過筆者測試,其被觸發的順序與,並且只與呼叫wait函式的順序相關,與其他(比如執行緒優先順序)條件沒有關係。這一點在開發時需要進行額外的考慮。

第三點:wait函式並不是完全可信的。這一點比較讓人蛋疼,也就是說wait返回後,並不代表對應的事件一定被觸發了,因此,為了保證執行緒之間的同步關係,使用nscondtion時往往需要加入乙個額外的變數來對非正常的wait返回進行規避。具體示例**如下:

//等待事件觸發的執行緒

[cocoacondition lock];

while (timetodowork <= 0)

[cocoacondition wait];

timetodowork--;

// do real work here.

[cocoacondition unlock];

//出發事件的執行緒

[cocoacondition lock];

timetodowork++;

[cocoacondition signal];

[cocoacondition unlock];

這個timetodowork就是那個額外需要的變數,在nscondition的使用中,這個變數是必不可少的。

nsconditon物件也是具名的,也就是說,其可於不同程序內部的執行緒同步。

相較於windows平台下提供的豐富的執行緒同步機制,ios下的執行緒同步機制稍顯單薄,但也正是這種簡潔簡化了其使用。

注:文中所指的執行緒同步泛指多執行緒環境下的同步與互斥。

iOS多執行緒程式設計 執行緒同步總結

1 原子操作 osatomic系列函式 ios平台下的原子操作函式都以osatomic開頭,使用時需要包含標頭檔案。不同執行緒如果通過原子操作函式對同一變數進行操作,可以保證乙個執行緒的操作不會影響到其他執行緒內對此變數的操作,因為這些操作都是原子式的。因為原子操作只能對內建型別進行操作,所以原子操...

多執行緒程式設計 執行緒同步

同步,永遠是多執行緒程式設計中最核心和最重要的話題.同步相關的概念比如 臨界區,原子操作,以及互斥量等等 總的來說,在多個執行緒之間採取同步措施,無非是為了讓他們更好的協同工作或者維持共享資料的一致性.1.共享資料的一致性 實際上,保證共享資料一致性的最簡單且最好的方法,就是使得該資料成為乙個常量,...

多執行緒程式設計2 執行緒同步

訊號量 訊號量通常有兩種 二進位制訊號量和計數訊號量。二進位制訊號量只有0和1兩種取值,計數訊號量有更大的取值範圍。訊號量一般用來保護一段 使其每次只能被乙個執行執行緒執行,要完成這個工作,可以使用二進位制訊號量。有時,希望可以允許有限數目的執行緒執行一段指定的 這時可以使用計數訊號量。建立 inc...