并行.用于最大线程和当前线程C#



我想要实现的目标:

使用Parallel.For(其他任何东西都可以,但发现这个是最简单的)我想增加一个名为max的变量,使其达到100,000,000,使用线程,但程序应该同时只使用X个线程。

代码片段:

using System;
using System.Threading;
using System.Linq;
using System.Threading.Tasks;
using System.Diagnostics;
namespace pool_threading
{
class MainClass
{
static int max=0;
static int current_max_thread=0;
public static void Main (string[] args)
{
Parallel.For(0, 100000000, new ParallelOptions { MaxDegreeOfParallelism = 50 },
i =>
{
max++;
if(Thread.CurrentThread.ManagedThreadId>current_max_thread)
current_max_thread=Thread.CurrentThread.ManagedThreadId;
});
Console.WriteLine ("I got to this number {0} using most {1} threads",max,current_max_tread);
}
public static void GetPage(int i)
{
}
}
}

结果:

我使用最多11个线程得到了这个数字38,786,886

现在。。。我不知道为什么我得到的数字38,786,886小于38,786,886,但我想这是因为多个线程试图在同一时间增加它,所以如果10个线程同时尝试,只有第一个线程会有机会。如果我错了,请纠正我。

最大的"问题"是,我一直得到11个线程,即使最大值设置为50(滚动代码查看最大值),如果我将其设置为最大值1个线程,我总是得到4(在这种情况下,可能4是最小值,但它仍然不能解释为什么我同时得到最大值只有11)。

这很简单,只需在循环中使用i,而不是尝试增量和使用max。你没有安全地增加它,但你没有理由尝试。Parallel.For的整个是它为您提供了循环索引,并确保每个循环索引只命中一次,不多也不少。

据我所知,这里有两件事:

首先,您正在从多个线程对max进行深入研究。你可能有一台多核机器。这些行动可能相互重叠。要以线程安全的方式执行增量,您需要

Interlocked.Increment(ref max);

不是

max++;   /* not thread safe */

其次,您并不总是得到MaxDegreeOfParallelism中要求的线程数。你永远不会得到更多,但你可能会得到更少。

如果要使用并行性,请密切注意将在线程中运行的代码的线程安全性。

我认为您没有得到50个线程,主要有两个原因:

  1. 硬件。处理器可以用更少的线程做更多的事情,因为切换线程所需的时间不仅仅是更频繁地运行线程。这导致

  2. 托管代码。NET是一个托管代码系统。.Net的程序员知道以上内容,可能会设置一些限制和检查,以防止过多的线程运行。您在代码中设置的内容可能高于某个内部限制,因此它实际上被忽略了。此外,您正在设置一个最大值,因此Parallel.For()可以使用从1到X的任何线程数,无论它认为什么是最有效的。

最新更新