• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

C# 线程同步与线程池 浅析

c# 搞代码 4年前 (2022-01-09) 12次浏览 已收录 0个评论

C# 线程同步与线程池

示例很简单,准备5个线程,每个线程同时向控制台输出数字,然后观察输出结果。

代码说明:

////线程列表

private static List<Thread> _threadList;          static voidMain(string[] args)        {            Program._threadList= new List<Thread>();            ////附加5个线程            for (inti = 0; i < 5; i++)            {                Program.AppendThread();            }             ////开始执行所有测试线程            Program.ExecuteThread();             ////按任意键退出            Console.ReadLine();        }         /// <summary>        /// 将新的测试线程附加到测试线程列表,线程执行逻辑就是输出10个数字/// 注意初始化的时候设置为后台线程了,这样可以保证主线程退出的时候其他线/// 程自动退出        /// </summary>        public staticvoid AppendThread()        {            Program._threadList.Add(newThread(new ThreadStart(                () =>                {                   for (int i = 0; i < 10; i++)                   {                       Console.WriteLine(i);                   }                })){ IsBackground = true });        }         /// <summary>        /// 开始执行所有测试线程        /// </summary>        public staticvoid ExecuteThread()        {            foreach(Thread t in _threadList)            {                t.Start();            }        }

观察执行结果,我们可以看到结果如下:

根据结果(数字的输出是不规律的)可知,线程之间发生了干扰。策略就是,加一个同步成员来进行线程同步:

   /// <summary>        /// 多线程同步的对象        /// </summary>        private static object _syncObj = new object();另外,在线程执行的地方加锁:Program._threadList.Add(newThread(new ThreadStart(                () =>                {                    lock (_syncObj)                    {                        for (int i = 0; i < 10;i++)                        {                            Console.WriteLine(i);                        }                    }                 })) { IsBackground = true });

观察结果:

可以看到通过Lock关键字,对一个多线程同步的变量加锁的确可以使得线程同步。

现在看一下第二种方式:

使用monitor关键字进行同步,代码:

Monitor.Enter(_syncObj);                   try                   {                       for (int i = 0; i < 10; <i>本文来源gaodai$ma#com搞$代*码网2</i>i++)                       {                            Console.WriteLine(i);                       }                   }                   finally {                       Monitor.Exit(_syncObj);                   }

查看结果,会发现线程已经同步了。

第三种方式:

现在让我们重构一下代码,新建一个ThreadManager的类,把类的职责都搬进去:

class ThreadManager    {        /// <summary>        /// 线程列表        /// </summary>        private staticList<Thread> _threadList;         staticThreadManager()        {           _threadList = new List<Thread>();        }         /// <summary>        /// 附加新线程        /// </summary>        public staticvoid AppendThread()        {            ThreadManager._threadList.Add(newThread(new ThreadStart(                () =>                {                   for (int i = 0; i < 10; i++)                   {                       Console.WriteLine(i);                   }                 })){ IsBackground = true });        }         /// <summary>        /// 开始执行所有线程        /// </summary>        public staticvoid ExecuteThread()        {            foreach(Thread t in _threadList)            {                t.Start();            }        }    }

Main函数调用的代码做相应的改变:

static voidMain(string[] args)        {            ////附加5个线程            for (int i = 0; i < 5; i++)            {                ThreadManager.AppendThread();            }             ////开始测试            ThreadManager.ExecuteThread();             ////按任意键继续            Console.ReadLine();        }

由于没有对线程同步做任何处理,结果肯定可以猜到,线程是不同步的:

现在对ThreadManager这个类加上特性:[Synchronization],再次运行之,发现线程同步了,这就是线程同步的第四种方案,用起来很简单,但是首先它要求执行逻辑都放在一个类中,由于它可以确保这个类中的所有方法都是线程安全的,因此它的性能相对低效

线程同步还有方法吗?答案是肯定的,那就是第四种方法—线程池。

现在来看一下如何用线程池来实现:

  static void Main(string[]args)        {/////定义一个waitCallback对象,并定义它的行为,就是向控制台输出十个数字同时可以传递/////一个参数(这个参数是可选的)                       WaitCallback work = new WaitCallback((o)=>            {                for(int i = 0; i < 10; i++)                {                   Console.WriteLine(i);                }            });             ////执行5次            for (inti = 0; i < 5; i++)            {/////如果这里需要传递参数,可以调用另一个重载方法                ThreadPool.QueueUserWorkItem(work);            }             ////按任意键继续            Console.ReadLine();        }

这样就完成了刚刚的逻辑吗?是的,运行之后我们可以看到结果,线程是同步的。

多线程还带来了哪些好处?

  • 线程池减少了线程创建、开始和停止的次数,从而提高了效率;

  • 使用线程池,能够使我们将注意力放到业务逻辑上而不是多线程架构上(然而在某些情况应优先使用手工线程管理)

  • 如果需要前台线程或者设置优先级别,或者线程池中的线程总是后台线程,且他的优先级是默认的;

  • 如果需要一个带有固定标识的线程便于退出,挂起或通过名字发现它。

以上就是C# 线程同步与线程池 浅析的内容,更多相关内容请关注搞代码(www.gaodaima.com)!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:C# 线程同步与线程池 浅析

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址