熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

C#多線程學習—生產者和消費者(1)

2022-06-13   來源: .NET編程 

    前面說過每個線程都有自己的資源但是代碼區是共享的即每個線程都可以執行相同的函數這可能帶來的問題就是幾個線程同時執行一個函數導致數據的混亂產生不可預料的結果因此我們必須避免這種情況的發生

    C#提供了一個關鍵字lock它可以把一段代碼定義為互斥段(critical section)互斥段在一個時刻內只允許一個線程進入執行而其他線程必須等待在C#中關鍵字lock定義如下

    lock(expression) statement_block

    expression代表你希望跟蹤的對象通常是對象引用

    如果你想保護一個類的實例一般地你可以使用this如果你想保護一個靜態變量(如互斥代碼段在一個靜態方法內部)一般使用類名就可以了

    而statement_block就是互斥段的代碼這段代碼在一個時刻內只可能被一個線程執行

    下面是一個使用lock關鍵字的典型例子在注釋裡說明了lock關鍵字的用法和用途

    示例如下

 using System;
using SystemThreading;

namespace ThreadSimple
{
    internal class Account
    {
        int balance;
        Random r = new Random();
       
        internal Account(int initial)
        {
            balance = initial;
        }

        internal int Withdraw(int amount)
        {
            if (balance < )
            {
                //如果balance小於則拋出異常
                throw new Exception(Negative Balance);
            }
            //下面的代碼保證在當前線程修改balance的值完成之前
            //不會有其他線程也執行這段代碼來修改balance的值
            //因此balance的值是不可能小於
            lock (this)
            {
                ConsoleWriteLine(Current Thread:+ThreadCurrentThreadName);
                //如果沒有lock關鍵字的保護那麼可能在執行完if的條件判斷之後
                //另外一個線程卻執行了balance=balanceamount修改了balance的值
                //而這個修改對這個線程是不可見的所以可能導致這時if的條件已經不成立了
                //但是這個線程卻繼續執行balance=balanceamount所以導致balance可能小於
                if (balance >= amount)
                {
                    ThreadSleep();
                    balance = balance amount;
                    return amount;
                }
                else
                {
                    return ; // transaction rejected
                  }
            }
        }
        internal void DoTransactions()
        {
            for (int i = ; i < ; i++)
            Withdraw(rNext( ));
        }
    }

    internal class Test
    {
        static internal Thread[] threads = new Thread[];
        public static void Main()
        {
            Account acc = new Account ();
            for (int i = ; i < ; i++)
            {
                Thread t = new Thread(new ThreadStart(accDoTransactions));
                threads[i] = t;
            }
            for (int i = ; i < ; i++)
                threads[i]Name=iToString();
            for (int i = ; i < ; i++)
                threads[i]Start();
            ConsoleReadLine();
        }
    }
}


From:http://tw.wingwit.com/Article/program/net/201311/15368.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.