天天看點

c# 多線程學習筆記(二)互斥,同步

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">互斥:是指某一資源同時隻允許一個通路者對其進行通路,具有唯一性和排它性。但互斥無法限制通路者對資源的通路順序,即通路是無序的。</span>
           

同步:是指在互斥的基礎上(大多數情況),通過其它機制實作通路者對資源的有序通路。在大多數情況下,同步已經實作了互斥,特别是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個通路者同時通路資源,如“第一類讀寫者模型”。

通過以下題目來說明互斥與同步:

程式描述:

主線程啟動10個子線程并将表示子線程式号的變量位址作為參數傳遞給子線程。子線程接收參數 ->sleep(50) -> 全局變量++ ->sleep(0) -> 輸出參數和全局變量。

要求:

1.子線程輸出的線程式号不能重複。

2.全局變量的輸出必須遞增。

分析:

1.主線程建立子線程并傳入一個指向變量位址的指針作參數,由于線程啟動須要花費一定的時間,是以在子線程根據這個指針通路并儲存資料前,主線程應等待子線程儲存完畢後才能改動該參數并啟動下一個線程。這涉及到主線程與子線程之間的同步。

2.子線程之間會互斥的改動和輸出全局變量。要求全局變量的輸出必須遞增。這涉及到各子線程間的互斥。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace SyncAndMutex
{
  
    class Program
    {
        static int mResource =0;
        static int threadcount = 10;
        static ManualResetEvent resetevent = new ManualResetEvent(false);
        static Object mCriticalSectionObj = new Object();
        static void Main(string[] args)
        {
            Pointer pt = new Pointer(0);
            for (int i = 0; i < threadcount; ++i)
            {
                Thread td = new Thread(ThreadTask);
                pt.PointValue = i;
                td.Start(pt);
                resetevent.WaitOne();
                resetevent.Reset();// if use the autoresetevent,it's unnecesary to call the reset()
            }
        } 

        static void ThreadTask(object threadorderid)
        {
            int id = ((Pointer)threadorderid).PointValue;//copy the value
            resetevent.Set();

            Monitor.Enter(mCriticalSectionObj);
            Thread.Sleep(50);
            mResource += 1;
            Thread.Sleep(0);
            Console.WriteLine("The Thread Order ID is " + id + " The Resource is " + mResource);
            Monitor.Exit(mCriticalSectionObj);
        }
    }

    class Pointer
    {
        public Pointer(int pointervalue)
        {
            mv = pointervalue;
        }

        int mv = -1;

        public int PointValue
        {
            get { return mv; }
            set { mv = value; }
        }
    }
}
           

在代碼中,為了展現出同步,是以專門建構class Pointer 作為參數,注意在此,如果将Int 型的i直接作為實參,那麼每次實參到形參object都會重新構造對象,這樣對于每一個子線程啟動線程函數,使用每一份object都是新的獨立的,進而将不需要同步操作。

 參考:

http://blog.csdn.net/morewindows/article/details/7442333

http://blog.csdn.net/MoreWindows/article/details/7442639

http://blog.csdn.net/MoreWindows/article/details/7470936

繼續閱讀