C# 多線程編程第二步——線程同步與安全執行緒

來源:互聯網
上載者:User

標籤:裝箱   pre   最好   阻塞   需要   表示   操作   開始   locker   

上一篇部落格學習了如何簡單的使用多線程。其實普通的多線程確實很簡單,但是一個安全的高效的多線程卻不那麼簡單。所以很多時候不正確的使用多線程反倒會影響程式的效能。

下面先看一個例子 :

   class Program    {        static int num = 1;        static void Main(string[] args)        {            Stopwatch stopWatch = new Stopwatch();            //開始計時            stopWatch.Start();            ThreadStart threadStart = new ThreadStart(Run);            for (int i = 0; i < 5; i++)            {                Thread thread = new Thread(threadStart);                thread.Start();            }            num++;            Console.WriteLine("num is:" + num);            Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());            //停止計時            stopWatch.Stop();            //輸出執行的時間,毫秒數            Console.WriteLine("The execution time is " + stopWatch.ElapsedMilliseconds + " milliseconds.");            Console.ReadKey();        }        public static void Run()        {            num++;            Console.WriteLine("num is:" + num);            Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());        }    }

執行結果:

從上面可以看出變數 num 的值不是連續遞增的,輸出也是沒有順序的,而且每次輸出的值都是不一樣的,這是因為非同步線程同時訪問一個成員時造成的,所以這樣的多線程對於我們來說是不可控的。以上這個例子就是非安全執行緒的,那麼要做到安全執行緒就需要用到線程同步。線程同步有很多種方法,比如之前用到過的 Join() 方法,它也可以實現線程的同步。下面我們來試試:

   class Program    {        static int num = 1;        static void Main(string[] args)        {            Stopwatch stopWatch = new Stopwatch();            //開始計時            stopWatch.Start();            ThreadStart threadStart = new ThreadStart(Run);            for (int i = 0; i < 5; i++)            {                Thread thread = new Thread(threadStart);                thread.Start();                thread.Join();            }            num++;            Console.WriteLine("num is:" + num);            Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());            //停止計時            stopWatch.Stop();            //輸出執行的時間,毫秒數            Console.WriteLine("The execution time is " + stopWatch.ElapsedMilliseconds + " milliseconds.");            Console.ReadKey();        }        public static void Run()        {            num++;            Console.WriteLine("num is:" + num);            Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());        }    }

執行結果:

這樣就實現了簡單的同步,相比起上面的代碼也就只是添加了一行代碼(thread.Join();),之前也提到了 Join() 這個方法用於阻止當前線程,直到前面的線程執行完成。可是這樣雖然是實現了同步,但是卻也阻塞了主線程的繼續執行,這樣和單線程貌似沒什麼區別了。既然這樣我們再去學習一下其他的方法。

實現線程同步還有一種鎖的機制,下面是一種最簡單的鎖機制,即使用 lock。如下:

   class Program    {        private object locker = new object();        int num = 1;        static void Main(string[] args)        {            Program program = new Program();            Stopwatch stopWatch = new Stopwatch();            //開始計時            stopWatch.Start();            ThreadStart threadStart = new ThreadStart(program.Run);            for (int i = 0; i < 5; i++)            {                Thread thread = new Thread(threadStart);                thread.Start();            }            program.num++;            Console.WriteLine("num is:" + program.num);            Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());            //停止計時            stopWatch.Stop();            //輸出執行的時間,毫秒數            Console.WriteLine("The execution time is " + stopWatch.ElapsedMilliseconds + " milliseconds.");            Console.ReadKey();        }        public void Run()        {            lock (locker)            {                num++;                Console.WriteLine("num is:" + num);                Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());            }        }    }

執行結果:

lock 是一種比較好用的簡單的線程同步方式,它是通過為給定對象擷取互斥鎖來實現同步的。可以看到這種方式的確沒有阻塞主線程,而且成員變數的值也是連續遞增的,說明是安全執行緒的。lock 鎖機製表示在同一時刻只有一個線程可以鎖定同步對象(在這裡是locker),任何競爭的的其它線程都將被阻止,直到這個鎖被釋放。

lock 的參數必須是基於參考型別的對象,不要是基本類型,比如 bool、int,這樣根本不能同步,原因是lock的參數要求是對象,如果傳入 int,勢必要發生裝箱操作,這樣每次lock的都將是一個新的不同的對象。最好避免使用public類型或不受程式控制的對象執行個體,因為這樣很可能導致死結。永遠也不要 lock 一個字串。

 

暫時先到這裡,後面學了其他方法在繼續更新。

 

C# 多線程編程第二步——線程同步與安全執行緒

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.