码迷,mamicode.com
首页 > 编程语言 > 详细

线程不安全与线程安全示例

时间:2018-01-26 12:45:23      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:分享图片   gpo   i++   实例   错误   read   info   style   col   

线程不安全与线程安全 示例代码:

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关键字来实现这种行为。如果锁定了一个对象,需要访问该对象的所有其他线程则会处于阻塞状态,并等待直到该对象解除锁定。注意:这里的线程安全代码可能会导致严重的性能问题。

 

线程不安全与线程安全示例

标签:分享图片   gpo   i++   实例   错误   read   info   style   col   

原文地址:https://www.cnblogs.com/lztkdr/p/NoThreadSafe_ThreadSafe_Demo.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!