.NET中各種線程同步鎖
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
編程編的久了,總會遇到多線程的情況,有些時候我們要幾個線程合作完成某些功能,這時候可以定義一個全局對象,各個線程根據這個對象的狀態(tài)來協同工作,這就是基本的 支持多線程編程的語言一般都內置了一些類型和方法用于創(chuàng)建上述所說的全局對象也就是 ps:本文雖然關注 .Net 平臺,但涉及到的大部分鎖概念都是平臺無關的,在很多其它語言(如_ volatile 關鍵字#確切地說, 緩存一致性#了解 我們知道,在現代計算機中,處理器的指令速度遠超內存的存取速度,所以現代計算機系統都不得不加入一層讀寫速度盡可能接近處理器運算速度的高速緩存來作為主存與處理器之間的緩沖。處理器計算直接存取的是高速緩存中的數據,計算完畢后再同步到主存中。 在多處理器系統中,每個處理器都有自己的高速緩存,而它們又共享同一主存。 而 Java 內存模型的每個線程有自己的工作內存,其中保留了被線程使用的變量的副本。線程對變量的所有的操作都必須在工作內存中完成,而不能直接讀寫主內存中的變量。不同線程之間也不能直接訪問對方工作內存中的變量,線程間變量的值的傳遞需要通過主內存中轉來完成。 雖然兩者的設計相似,但是前者主要解決存取效率不匹配的問題,而后者主要解決內存安全(競爭、泄露)方面的問題。顯而易見,這種設計方案引入了新的問題—— 為了解決這個問題,很多平臺都內置了 volatile 關鍵字,使用它修飾的變量,可以保證所有線程每次獲取到的是最新值。這是怎么做到的呢?這就要求所有線程在訪問變量時遵循預定的協議,比如 另外 volatile 還能避免編譯器自作聰明重排指令。重排指令在大多數時候無傷大雅,還能對執(zhí)行效率有一定提升,但某些時候會影響到執(zhí)行結果,此時就可以使用 volatile。 Interlocked#同 volatile 的 它的原子操作基于 CPU 本身,非阻塞,所以也不是真正意義上的鎖,當然效率會比鎖高得多。 鎖模式#接下來正式介紹各種鎖之前,先了解下鎖模式——鎖分為 內核模式就是在系統級別讓線程中斷,收到信號時再切回來繼續(xù)干活。該模式在線程掛起時由系統底層負責,幾乎不占用 CPU 資源,但線程切換時效率低。 用戶模式就是通過一些 CPU 指令或者死循環(huán)讓線程一直運行著直到可用。該模式下,線程掛起會一直占用 CPU 資源,但線程切換非常快。 長時間的鎖定,優(yōu)先使用內核模式鎖;如果有大量的鎖定,且鎖定時間非常短,切換頻繁,用戶模式鎖就很有用。另外內核模式鎖可以實現跨進程同步,而用戶模式鎖只能進程內同步。 本文中,除文末 lock 關鍵字#
Monitor#上面 lock 就是
Monitor 還可以設置超時時間,避免無限制的等待。同時它還有 ReaderWriterLock#很多時候,對資源的讀操作頻率要遠遠高于寫操作頻率,這種情況下,應該對讀寫應用不同的鎖,使得在沒有寫鎖時,可以并發(fā)讀(加讀鎖),在沒有讀鎖或寫鎖時,才可以寫(加寫鎖)。 主要的特點是在沒有寫鎖時,可以并發(fā)讀,而非一概而論,不論讀寫都只能一次一個線程。 MethodImpl(MethodImplOptions.Synchronized)#如果是方法層面的線程同步,除上述的 SynchronizationAttribute#ContextBoundObject#要了解 首先進程中承載程序集運行的邏輯分區(qū)我們稱之為 在上下文的接口當中存在著一個消息接收器負責檢測攔截和處理信息。當對象是 而 ps: 相對的,沒有繼承自 ContextBoundObjec t的類的實例則被視為 一個進程內可以包括多個應用程序域,也可以有多個線程。線程可以穿梭于多個應用程序域當中,但在同一個時刻,線程只會處于一個應用程序域內。線程也能穿梭于多個上下文當中,進行對象的調用。
WaitHandle#在查閱一些異步框架的源碼或接口時,經常能看到 WaitHandle 包含有以下幾個派生類:
ManualResetEvent#可以阻塞一個或多個線程,直到收到一個信號告訴 ManualResetEvent 不要再阻塞當前的線程。 注意所有等待的線程都會被喚醒。 可以想象 ManualResetEvent 這個對象內部有一個信號狀態(tài)來控制是否要阻塞當前線程,有信號不阻塞,無信號則阻塞。這個信號我們在初始化的時候可以設置它,如 代碼舉例:
AutoResetEvent#用法上和 ManualResetEvent 差不多,不再贅述,區(qū)別在于內在邏輯。 與 ManualResetEvent 不同的是,當某個線程調用Set方法時,只有一個等待的線程會被喚醒,并被允許繼續(xù)執(zhí)行。如果有多個線程等待,那么只會隨機喚醒其中一個,其它線程仍然處于等待狀態(tài)。 另一個不同點,也是為什么取名 CountdownEvent#它的信號有計數狀態(tài),可遞增 注意:CountdownEvent 是用戶模式鎖。 Mutex#Mutex 這個對象比較“專制”,同時段內只能準許一個線程工作。 Semaphore#對比 Mutex 同時只有一個線程工作, 輕量級同步#.NET Framework 4 開始,System.Threading 命名空間中提供了六個新的數據結構,這些數據結構允許細粒度的并發(fā)和并行化,并且降低一定必要的開銷,它們稱為輕量級同步原語,它們都是用戶模式鎖,包括:
Barrier#當在需要一組任務并行地運行一連串的階段,但是每一個階段都要等待其他任務完成前一階段之后才能開始時,您可以通過使用 SpinWait#如果等待某個條件滿足需要的時間很短,而且不希望發(fā)生昂貴的上下文切換,那么基于自旋的等待時一種很好的替換方案。 需要注意的是:長時間的自旋不是很好的做法,因為自旋會阻塞更高級的線程及其相關的任務,還會阻塞垃圾回收機制。SpinWait 并沒有設計為讓多個任務或線程并發(fā)使用,因此需要的話,每一個任務或線程都應該使用自己的 SpinWait 實例。 當一個線程自旋時,會將一個內核放入到一個繁忙的循環(huán)中,而不會讓出當前處理器時間片剩余部分,當一個任務或者線程調用 因此,在大部分情況下, 不要在循環(huán)內調用 Thread.Sleep 方法等待特定的條件滿足 。
轉自https://www.cnblogs.com/newton/p/18365359 該文章在 2024/8/19 8:31:40 編輯過 |
關鍵字查詢
相關文章
正在查詢... |