線程不安全與線程安全示例


線程不安全與線程安全 示例代碼:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Incorrect counter");

            var c = new Counter();

            var t1 = new Thread(() => TestCounter(c));
            var t2 = new Thread(() => TestCounter(c));
            var t3 = new Thread(() => TestCounter(c));
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();

            Console.WriteLine("Total count: {0}",c.Count);
            Console.WriteLine("--------------------------");

            Console.WriteLine("Correct counter");

            var c1 = new CounterWithLock();

            t1 = new Thread(() => TestCounter(c1));
            t2 = new Thread(() => TestCounter(c1));
            t3 = new Thread(() => TestCounter(c1));
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();
            Console.WriteLine("Total count: {0}", c1.Count);

            Console.ReadKey();
        }

        static void TestCounter(CounterBase c)
        {
            for (int i = 0; i < 100000; i++)
            {
                c.Increment();
                c.Decrement();
            }
        }

        class Counter : CounterBase
        {
            public int Count { get; private set; }

            public override void Increment()
            {
                Count++;
            }

            public override void Decrement()
            {
                Count--;
            }
        }

        class CounterWithLock : CounterBase
        {
            private readonly object _syncRoot = new Object();

            public int Count { get; private set; }

            public override void Increment()
            {
                lock (_syncRoot)
                {
                    Count++;
                }
            }

            public override void Decrement()
            {
                lock (_syncRoot)
                {
                    Count--;
                }
            }
        }

        abstract class CounterBase
        {
            public abstract void Increment();

            public abstract void Decrement();
        }
    }

線程不安全與線程安全 執行結果:

線程不安全與線程安全 工作原理:

             當主程序啟動時,創建了一個Counter類的對象。該類定義了一個可以遞增和遞減的簡單的計數器。然后我們啟動了三個線程。這三個線程共享同一個counter實例,在一個周期中進行一次遞增和一次遞減。這將導致不確定的結果。如果運行程序多次,則會打印出多個不同的計數器值。結果可能是0,但大多數情況下則不是0。

             這是因為Counter類並不是線程安全的。當多個線程同時訪問counter對象時,第一個線程得到的counter值10並增加為11。然后第二個線程得到的值是11並增加為12。第一個線程得到counter值12,但是遞減操作發生前,第二個線程得到的counter值也是12。然后第一個線程將12遞減為11並保存回counter中,同時第二個線程進行了同樣的操作。結果我們進行了兩次遞增操作但是只有一次遞減操作,這顯然不對。這種情形被稱為競爭條件(race condition)。競爭條件是多線程環境中非常常見的導致錯誤的原因。

             為了確保不會發生以上情形,必須保證當有線程操作counter對象時,所有其他線程必須等待直到當前線程完成操作。我們可以使用lock關鍵字來實現這種行為。

             如果鎖定了一個對象,需要訪問該對象的所有其他線程則會處於阻塞狀態,並等待直到該對象解除鎖定。

             注意:這里的線程安全代碼可能會導致嚴重的性能問題。

 


免責聲明!

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



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