C# 語言的多線程編程,完全是本科OS里的知識


 基本知識,無參數Thread和帶參數的Thread

Thread類的參數就是參數指針,可以傳入一個無參的函數。

如果要傳入帶參數的函數,先new一個ParameterizedThreadStart委托實例,帶參數的函數名作為它的參數。帶參數的函數必須且只能有一個object參數。參考下面的

ConterWithParam(object param)

 

static int iCnt = 0;
        static readonly int N = 10000;

        static void Main(string[] args)
        {
            Thread[] thrs = new Thread[N];
            for (int i = 0; i < N; i++)
            {
                thrs[i] = new Thread(Counter);
                thrs[i].Start();               
            }
            for (int i = 0; i < N; i++)
            {              
                thrs[i].Join();
            }
            Console.WriteLine(iCnt);

            iCnt = 0;

            ParameterizedThreadStart[] thrsp = new ParameterizedThreadStart[N];
            object param = 2;
            for (int i = 0; i < N; i++)
            {
                thrsp[i] = new ParameterizedThreadStart(ConterWithParam);
                thrs[i] = new Thread(thrsp[i]);
                thrs[i].Start(param);
            }
            for (int i = 0; i < N; i++)
            {
                //當NewThread調用Join方法的時候,MainThread就被停止執行,直到NewThread線程執行完畢
                thrs[i].Join();
            }
            Console.WriteLine(iCnt);
        }

        static void Counter()
        {
            Thread.Sleep(100);
            iCnt++;
            //Console.WriteLine("finish iCnt++,now iCnt is " + iCnt);            
        }

        static void ConterWithParam(object param)
        {
            Thread.Sleep(100);
            int i = (int)param;
            iCnt += i;
            //Console.WriteLine("finish iCnt+"+i+",now iCnt is " + iCnt);     
        }

 

該例子輸出結果

2)互斥信號燈mutex

第一節的結果是不是有點奇怪。明明加了10000次,結果卻是9550.

帶參數的那個例子,一次加2,加10000次,應該是20000才對。結果卻是19678.

這是因為對全局變量的訪問iCnt出現了沖突。比如兩個線程同時取到了iCnt=0時的值,同時執行了i++,那么iCnt的最后狀態肯定是1,而不是會2。為了讓iCnt得到正確的值。

我們引入互斥信號燈。

static int iCnt = 0;
        static readonly int N = 10000;
        static Mutex mut = new Mutex();

        static void Main(string[] args)
        {
            Thread[] thrs = new Thread[N];
            for (int i = 0; i < N; i++)
            {
                thrs[i] = new Thread(Counter);
                thrs[i].Start();               
            }
            for (int i = 0; i < N; i++)
            {              
                thrs[i].Join();
            }
            Console.WriteLine(iCnt);

            iCnt = 0;

            ParameterizedThreadStart[] thrsp = new ParameterizedThreadStart[N];
            object param = 2;
            for (int i = 0; i < N; i++)
            {
                thrsp[i] = new ParameterizedThreadStart(ConterWithParam);
                thrs[i] = new Thread(thrsp[i]);
                thrs[i].Start(param);
            }
            for (int i = 0; i < N; i++)
            {
                //當NewThread調用Join方法的時候,MainThread就被停止執行,直到NewThread線程執行完畢
                thrs[i].Join();
            }
            Console.WriteLine(iCnt);
        }

        static void Counter()
        {
            Thread.Sleep(10);
            //
            mut.WaitOne();            
            iCnt++;
            //釋放
            mut.ReleaseMutex();
            //Console.WriteLine("finish iCnt++,now iCnt is " + iCnt);            
        }

        static void ConterWithParam(object param)
        {
            Thread.Sleep(10);
            //鎖住
            mut.WaitOne();            
            int i = (int)param;
            iCnt += i;
            //釋放
            mut.ReleaseMutex();
            //Console.WriteLine("finish iCnt+"+i+",now iCnt is " + iCnt);     
        }

 

本次執行結果

3) 同步信號燈Semaphore

用最經典的生產者-消費者來解釋。

static Semaphore sem = new Semaphore(0, 1);
        static Semaphore sem2 = new Semaphore(0, 5);

        static void Main(string[] args)
        {
            Console.WriteLine("消費者等生產者生產一個item");
            Thread thConsumer = new Thread(Consume);
            thConsumer.Start();
            Thread thProductor = new Thread(Product);
            thProductor.Start();

            thConsumer.Join();
            thProductor.Join();
            Console.WriteLine(".............................");

            Console.WriteLine("多並發的例子.....");
            for (int i = 0; i < 10; i++)
            {
                Thread t1 = new Thread(Consume2);
                t1.Start();
                Thread t2 = new Thread(Product2);
                t2.Start();
            }//end for
            

        }


        static void Product()
        {
            Thread.Sleep(2000);
            Console.WriteLine("Product an item...");
            sem.Release();
        }

        static void Consume()
        {
            Thread.Sleep(1000);
            Console.WriteLine("Consumer is waiting an item...");
            sem.WaitOne();
            Console.WriteLine("Consumer get an item...");
        }



        static void Product2()
        {
            Thread.Sleep(1000);
            Console.WriteLine("Product an item...");
            sem2.Release();
        }

        static void Consume2()
        {
            Thread.Sleep(1000);
            Console.WriteLine("Consumer is waiting an item...");
            sem2.WaitOne();
            Console.WriteLine("Consumer get an item...");
        }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM