前面幾篇咱們介紹了線程同步的臨界區、互斥量、事件、信號量四種方式。 .NET中線程同步的方式多的讓人看了眼花繚亂,究竟該怎麼去理解呢?其實,咱們拋開.NET環境看線程同步,無非是執行兩種操做:一是互斥/加鎖,目的是保證臨界區代碼操做的「原子性」;另外一種是信號燈操做,目的是保證多個線程按照必定順序執行,如生產者線程要先於消費者線程執行。.NET中線程同步的類無非是對這兩種方式的封裝,目的歸根結底均可以歸結爲實現互斥/加鎖或者是信號燈這兩種方式,只是它們的適用場合有所不一樣。下面咱們下來總結一下以前幾種同步方式的區別,而後再講一下原子操做Interlockedspa
1、幾種同步方法的區別操作系統
lock和Monitor是.NET用一個特殊結構實現的,Monitor對象是徹底託管的、徹底可移植的,而且在操做系統資源要求方面可能更爲有效,同步速度較快,但不能跨進程同步。lock(Monitor.Enter和Monitor.Exit方法的封裝),主要做用是鎖定臨界區,使臨界區代碼只能被得到鎖的線程執行。Monitor.Wait和Monitor.Pulse用於線程同步,相似信號操做,我的感受使用比較複雜,容易形成死鎖。線程
互斥體Mutex和事件對象EventWaitHandler屬於內核對象,利用內核對象進行線程同步,線程必需要在用戶模式和內核模式間切換,因此通常效率很低,但利用互斥對象和事件對象這樣的內核對象,能夠在多個進程中的各個線程間進行同步。code
互斥體Mutex相似於一個接力棒,拿到接力棒的線程才能夠開始跑,固然接力棒一次只屬於一個線程(Thread Affinity),若是這個線程不釋放接力棒(Mutex.ReleaseMutex),那麼沒辦法,其餘全部須要接力棒運行的線程都知道能等着看熱鬧。對象
EventWaitHandle 類容許線程經過發信號互相通訊。一般,一個或多個線程在 EventWaitHandle 上阻止,直到一個未阻止的線程調用 Set 方法,以釋放一個或多個被阻止的線程。blog
2、原子操做Interlocked進程
Interlocked提供不少方法執行原子操做,下邊將詳細介紹事件
一、Increment自增效果 資源
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace InterLocked { class Program { static void Main(string[] args) { for (int i = 0; i < 20; i++) { Thread t = new Thread(Run); t.Start(); } Console.Read(); } static int count = 0; static Mutex mutex = new Mutex(); static void Run() { mutex.WaitOne(); Thread.Sleep(100); Console.WriteLine("當前數字:{0}", Interlocked.Increment(ref count)); mutex.ReleaseMutex(); } } }
二、Decrement自減操做rem
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace InterLocked { class Program { static void Main(string[] args) { for (int i = 0; i < 20; i++) { Thread t = new Thread(Run); t.Start(); } Console.Read(); } static int count = 20; static Mutex mutex = new Mutex(); static void Run() { mutex.WaitOne(); Thread.Sleep(100); Console.WriteLine("當前數字:{0}", Interlocked.Decrement(ref count)); mutex.ReleaseMutex(); } } }
三、Add加法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace InterLocked { class Program { static void Main(string[] args) { int i = 10; Interlocked.Add(ref i, 20); Console.WriteLine(i); //i=30 Console.ReadKey(); } } }
四、Exchange 賦值操做
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace InterLocked { class Program { static void Main(string[] args) { int i = 10; Interlocked.Exchange(ref i, 30); Console.WriteLine(i); //i=30 Console.ReadKey(); } } }
InterLocked類還有不少方法,這裏就不一一介紹了。。。。。。。。。。。。。。