**程安全的單間類中提到了interlockedcompareexchangepointer
函式及cas(compare and swap)技術,或者成為lock free,及使用系統提供的基於cpu指令的無鎖多執行緒資料同步技術。這裡打算稍微學習並總結下windows平台下常用的多執行緒資料同步方法以及他們的區別。
多執行緒同步,最常用的應該是加鎖。常見的方式有臨界區、訊號量、互斥鎖等。
臨界區是windows下的,是使用者態的同步,開銷小、速度快,適合用於控制多執行緒資料訪問。不可用於程序間資料同步。首先進入臨界區的執行緒執行,其他執行緒掛起。
互斥鎖在windows和linux都可用,各執行緒爭搶鎖,搶到鎖的執行緒可執行,其他現成掛起等待。互斥鎖可以用於執行緒同步,也可以用於程序同步。工作在核心態,相對來說開銷大,速度慢。
訊號量用在多執行緒多工同步的,乙個執行緒完成了某乙個動作就通過訊號量告訴別的執行緒,別的執行緒再進行某些動作。核心態。
和lock free相比,上面的同步方式都先的少重,對於頻繁訪問的一些資源,如果使用鎖來同步,就會有比較大的開銷。在某些場景下,使用lock free,在效能上會有一定的優化。
lock free 基於 cas(compare and swap)以及atomic。先介紹下一組atomic。
原子操作是不可分割的,在執行完畢不會被任何其它任務或事件中斷,不會被
執行緒排程
機制打斷的操作;這種操作一旦開始,就一直執行到結束,中間不會有任何 context switch (切換到另乙個執行緒)
long __cdecl interlockedincrement(_inout_ long volatile *addend);//原子+1
long __cdecl interlockeddecrement(_inout_ long volatile *addend);//原子-1
long __cdecl interlockedexchangeadd(_inout_ long volatile *addend,_in_ long value);//原子+n(n可為負數)
long __cdecl interlockedexchange(_inout_ long volatile *target,_in_ long value);//原子賦值
long __cdecl interlockedcompareexchange(_inout_ long volatile *destination,_in_ long exchange,_in_ long comparand);//原子比較賦值
pvoid __cdecl interlockedcompareexchangepointer(_inout_ pvoid volatile *destination,_in_ pvoid exchange,_in_ pvoid comparand);//原子指標比較賦值
為什麼對乙個自增操作需要原子操作interlockedincrement?
這是因為一條簡單的i += 1或者i++指令,在cpu執行時,是由多條指令組合而成的。
1.將i從記憶體取出,並動態生成乙個空間儲存取出來的值;
2.將取出來的值和1做加法,並將和放入i的空間覆蓋掉原值,操作結束;
起碼有兩步,那麼它就不是原子操作。當有多個執行緒時,有可能在step1和step2之間由於執行緒切換而造成資料異常。
而interlockedincrement就保證了對乙個數i的自增操作是原子的,自動實現執行緒同步。可以認為interlockedincrement內****的,當然,它需要cpu的支援:
interlockedincrement(¶m)
interlockeddecrement和interlockedincrement類似,他們常用於引用計數的增減。
interlockedexchangeadd可以實現+n操作。
interlockedexchange實現給賦值的原子操作。
interlockedcompareexchange實現比較賦值,如果destination等於compare,則將exchange的值賦給destination。
interlockedcompareexchangepointer是對指標的比較賦值。
上面這些原子操作api更多的是在lock free中和其他結合使用。可參看並行程式設計中的lock free
最後加一句,關於sleep操作。加鎖造成的執行緒等待,執行緒將被掛起,而sleep操作並不會掛起執行緒。sleep把程序的執行狀態改為睡眠,將其從系統可執行佇列去掉,這樣系統就不會排程到該程序,不會分配cpu時間片。同時根據該程序的睡眠時間,將程序掛入相應的定時器佇列中。
同時核心維持乙個定時器佇列,每一次時鐘中斷處理,都把當前到期的佇列中的程序喚醒,加入到可執行程序佇列中。 同時對所有掛入定時器佇列中的程序時間值減1。所以即使sleep(0),當前執行緒也會交出當前cpu時間片中未使用的部分。理解了這些,對於處理cpu占用高的效能問題,使用sleep(0)或sleep(1)會有一定幫助。
多執行緒同步總結
同步方式 是否為核心物件 特點模擬場景 臨界區非核心物件 通過多執行緒的序列化來訪問公共資源或一段 速度快,適合控制資料訪問。在任意時刻只允許乙個執行緒對臨界區的訪問。亭訊號量 核心物件 它允許多個執行緒在同一時刻訪問統一資源,但是需要限制同一時刻訪問此資源的最大執行緒數目。停車場剩餘車位數目 互斥...
iOS多執行緒程式設計 執行緒同步總結
1 原子操作 osatomic系列函式 ios平台下的原子操作函式都以osatomic開頭,使用時需要包含標頭檔案。不同執行緒如果通過原子操作函式對同一變數進行操作,可以保證乙個執行緒的操作不會影響到其他執行緒內對此變數的操作,因為這些操作都是原子式的。因為原子操作只能對內建型別進行操作,所以原子操...
iOS多執行緒程式設計 執行緒同步總結
1 原子操作 osatomic系列函式 ios平台下的原子操作函式都以osatomic開頭,使用時需要包含標頭檔案。不同執行緒如果通過原子操作函式對同一變數進行操作,可以保證乙個執行緒的操作不會影響到其他執行緒內對此變數的操作,因為這些操作都是原子式的。因為原子操作只能對內建型別進行操作,所以原子操...