ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

1.10 使用C#中的lock关键字

2022-08-07 14:03:13  阅读:257  来源: 互联网

标签:1.10 C# lock void counter System 线程 using new


1. 本节将描述如何确保当一个线程使用某些资源时,同时其他线程无法使用该资源。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace ConsoleApp1
{
    class Program
    {
        /// <summary>
        /// 当主程序启动时,创建了一个Counter类的对象。该类定义了一个可以递增和递减的简单的计数器。
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            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();

            WriteLine($"Total count:{c.Count}");
            WriteLine("------------------------------------");

            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();
            WriteLine($"Total count:{c1.Count}");
        }
        static void TestCounter(CounterBase c)
        {
            for (int i = 0; i < 100000; i++)
            {
                c.Increment();
                c.Decrement();
            }
        }
    }
    /// <summary>
    /// 该类定义了一个可以递增和递减的简单的计数器。
    /// </summary>
    class Counter : CounterBase
    {
        public int Count { get; private set; }
        public override void Decrement()
        {
            Count--;
        }

        public override void Increment()
        {
            Count++;
        }
    }
    class CounterWithLock : CounterBase
    {
        private readonly object _syncRoot=new object();
        public int Count { get; private set; }

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

        public override void Increment()
        {
            lock (_syncRoot)
            {
                Count++;
            }
        }
    }
    abstract class CounterBase
    {
        public abstract void Increment();
        public abstract void Decrement();
    }
}

2 工作原理

当主程序启动时,创建了一个Counter类的对象。该类定义了一个可以递增和递减的简单的计数器。然后我们启动了三个线程。这三个线程共享同一个counter示例,在一个周期中进行一次递增和一次递减。这将导致不确定的情况。如果运行程序多次,则会打印出多个不同的计数器的值。结果可能是0,单大多数情况下则不是0。

这是因为Counter类并不是线程安全的。当多个线程同时访问counter对象时,第一个线程得到的counter值10并增加为11.然后第二个线程得到的值是11并增加为12。第一个线程得到counter值12,但是递减操作发生前,第二个线程得到的counter值也是12.然后第一个线程将12递减为11并保存回counter中,同时第二个线程进行了同样的操作。结果我们进行了两次递增操作但是只有一次递减操作,这显然不对。这种情形被称为竞争条件(racecondition)。竞争条件是多线程环境中非常常见的导致错误的原因。

为了确保不会发生以上情形,必须保证当有线程操作counter对象时,所有其他线程必须等待直到当前线程完成操作。我们可以使用lock关键字来实现这种行为。如果锁定了一个对象,需要访问该对象的所有其他线程则会处于阻塞状态,并等待直到该对象解除锁定。这可能会导致严重的性能问题。

 

标签:1.10,C#,lock,void,counter,System,线程,using,new
来源: https://www.cnblogs.com/cherry1022/p/16558953.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有