多線程總結之旅(10):線程同步之原子操做

  前面幾篇咱們介紹了線程同步的臨界區、互斥量、事件、信號量四種方式。 .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類還有不少方法,這裏就不一一介紹了。。。。。。。。。。。。。。
相關文章
相關標籤/搜索