經驗總結 C 常用執行緒同步方法應用場景和實現原理

2021-09-06 02:02:53 字數 2468 閱讀 4577

簡單描述volatile,interlocked,lock,mutex,semaphore,spin lock,autoresetevent,manualresetevent,readerwriterlockslim,methodimplattribute,waithandle常用同步機制的原理和使用場景。

volatile

只是c#的乙個關鍵字,告訴編譯器不能將宣告的這個變數進行cpu內部快取,只能在主記憶體中操作,型別有限制,volatile並不能實現真正的同步,因為它的操作級別只停留在變數級別,而不是原子級別。如果是在單處理器系統中,是沒有任何問題的,變數在主存中沒有機會被其他人修改,因為只有乙個處理器,這就叫作processor self-consistency。但在多處理器系統中,可能就會有問題。 每個處理器都有自己的data cache,而且被更新的資料也不一定會立即寫回到主存。所以可能會造成不同步,但這種情況很難發生,因為cache的讀寫速度相當快,flush的頻率也相當高,只有在壓力測試的時候才有可能發生,而且機率非常非常小。本質上說並非絕對的同步方法。

interlocked

對於例如int變數等的原子操作,效率高,可靠性高,一般通過cpu的專用指令實現的鎖住記憶體匯流排實現的。

lock

lock與monitor本身是一致的,lock是做到了c#的關鍵字一級,是.net物件自身支援的的一種同步機制,物件中有相關的結構支援這種輕量級的執行緒同步,實現機制類似於critical_section,但是critical_section具有跨程序特性,而lock只能實現同一程序中的執行緒同步,在c#開發中很常用。

mutex

是win32下的突變體核心物件的封裝,類似於一間屋子只能進入乙個人。是它的乙個.net封裝,效率比較低,由於突變體是一種windows核心物件,需要開銷很大,但是支援跨程序,通過給mutex命名的方式支援程序間同步,甚至可以跨伺服器訪問,是一種伺服器之間同步的選擇。mutex的擁有者才能釋放這個mutex,其他程序不能釋放,可能是考慮到安全問題。mutex是一種基於執行緒排程的同步方式,控制的是執行緒的排程,實現了sleep,如果有訊號可以通知核心執行緒排程程式排程等待執行緒。

semaphore(binary semaphore)

基於win32的semaphore,也是一種基於執行緒排程,基本很類似於mutex,與mutex不同之處在於semaphore允許多人進入同一間屋子,使用count計數來實現,當允許數量為1時叫做binary semaphore,這時候就是基本和mutex很類似的,但是沒有mutex擁有者一說,可由任何程序進行資源釋放。

spin lock

這是乙個核心態概念。spin lock與semaphore的主要區別是spin lock是busy waiting,而semaphore是sleep。對於可以sleep的程序來說,busy waiting當然沒有意義,cpu只是在那裡空轉而已,而且irql比較高,適合於等待時間比較短的場景。對於單cpu的系統,busy waiting當然更沒意義(沒有cpu可以釋放鎖),所有spin lock只對多cpu才有意義,因此,只有多cpu的核心態非程序空間,才會用到spin lock。其實也就是類似mutex的作用,序列化對 critical section的訪問。但是mutex不能保護中斷的打斷,也不能在中斷處理程式中被呼叫。而spin lock也一般沒有必要用於可以sleep的程序空間。幸好它是核心級的,如果是使用者級的會很危險。

autoresetevent,manualresetevent  (event)

這兩種的實現都是基於win32的event原理,同步事件有兩種:autoresetevent 和 manualresetevent。它們之間唯一的不同在於,無論何時,只要 autoresetevent 啟用執行緒,它的狀態將自動從終止變為非終止。相反,manualresetevent 允許它的終止狀態啟用任意多個執行緒,只有當它的 reset 方法被呼叫時才還原到非終止狀態。

readerwriterlockslim

這個也是lock的封裝,對資源的訪問方式有共享和獨佔方式,例如我們控制對某個資源讀貢獻或者寫獨佔,那麼這個類可以派上用場。

synchronizationattribute ,methodimplattribute

這兩個屬於類特性和方法的特性,標識某個類或方法是同步方法,本質上基於lock的實現。

waithandle

可以通過呼叫一種等待方法,如 waitone、waitany 或 waitall,讓執行緒等待事件。system.threading.waithandle.waitone 使執行緒一直等待,直到單個事件變為終止狀態;system.threading.waithandle.waitany 阻止執行緒,直到乙個或多個指示的事件變為終止狀態;system.threading.waithandle.waitall 阻止執行緒,直到所有指示的事件都變為終止狀態。當呼叫事件的 set 方法時,事件將變為終止狀態。waitone基於waitsingleobject,waitany 或 waitall基於waitmultipleobject,具體由後面引數來決定。waitmultipleobject實現要比waitsingleobject複雜的多,效能也不好,盡量少用。

C 經驗總結

1.標準庫的使用過程中,自己一定要注意,不能使用迭代器保留,因為新的stl中,加入了迭代器新的檢測機制,就是為了怕使用者使用的過程中自己將迭代器有意無意的引用了不存在的物件,因此這就要求我們的迭代器物件一定要在訪問的物件之前進行析購,否則你的程式將出錯。這個是c v8.0 中ms 加入新的安全機制,...

JS常用經驗總結

function getallquery let query null if list.length 1 else let vars query.split for let i 0 i1 單例模式 定義 保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點。實現的方法為先判斷例項存在與否,如果存在...

linux sync檔案同步之經驗總結

今天研究了一下關於 在linux上資料同步的問題。a伺服器上的檔案同步到b c伺服器 rsync服務端做的設定如下 rsync安裝省略 在a伺服器上做如下配置 1,安裝rsync服務,檢視rsync服務命令是ps ef grep rsync,啟動rsync命令是rsync daemon。2,etc ...