技术开发 频道

在.NET上执行多线程操作要考虑的两大因素

  【IT168 技术文档】

  线程管理

  线程管理现在变得越来越容易了。在.NET架构中,你可以从线程池中获取线程。线程池是一个生成线程的工厂,如果它已经生成了一定数量的线程且还没有被破坏的话,对它的调用会被阻止。但是,如何确保不会有太多的线程在规定时间内运行?毕竟,如果每个线程能够占用一个CPU核的100%,那么有超过CPU核数量的线程运行,只会导致操作系统启动线程时间分配,这将导致上下文切换和低效率运行。换句话说,同一核上的两个线程不会以两倍的时长完成,可能需要用两倍再加10 %左右的时间来完成。与一个线程相比较的话,三个线程在同一核上想占用100 %的CPU使用率可能会需要3.25——3.5倍的时长来完成。我的经验是,每个核都有多个线程试图占用100 %的CPU,但它们都不能达到目标。

  所以,要怎样分配正在运行的线程数量呢?

  有一个办法是在线程之间建立一个共享的旗语对象。在线程开始运行前,它会尝试调用旗语的WaitOne模式,并在完成后释放旗语。对CPU的核数量设置旗语限制,(使用EnvironmentProcessorCount功能限定);这将防止您的系统在同一时间运行的线程数多于核数量。与此同时,从线程池中拉出线程将确保您不会在同一时间创建过多线程。如果一次创建线程过多,即使他们并没运行,那也是浪费系统资源。因为每个线程都要消耗资源。使用旗语的一般模式如下所示:

  以下为引用的内容: 

   static Semaphore threadBlocker;

  
static void Execute(object state)

  { threadBlocker.WaitOne();
//Do work threadBlocker.Release(); }

  
static void RunThreads()

  { threadBlocker
= new Semaphore(0, Environment.ProcessorCount); for (int x = 0; x <= 2000; x++) {ThreadPool.QueueUserWorkItem(new WaitCallback (Execute)); } }

  当然还有其他一些办法可以解决这一问题。前一段时间我想要保持对象的一份〈T〉清单。每个对象代表每个工人部件的完整状态。执行和完成时,工人部件都会被填入数据。并且他会设置某个功能以指示任务完成。主线程将扫描对象清单,如果运行的线程数量足够少,就开始运行另一个。说实话,虽然这个方法可行,但对于代码和调试来说这绝对是个噩梦,所以我一点也不推荐。

0
相关文章