我想要实现的目标:
使用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。)
答案 0 :(得分:2)
这很简单,只需在循环内部使用i
,而不是尝试增加并使用max
。你没有安全地增加它,但你没有理由去尝试。 Parallel.For
的整个点是它给你循环索引,并确保每个循环索引只被命中一次,不多也不少。
答案 1 :(得分:1)
据我所知,这里有两件事:
首先,你正在从多个线程中瞄准max
。你可能有一台多核机器。这些操作可能彼此重叠。要以线程安全的方式执行递增,需要
Interlocked.Increment(ref max);
不
max++; /* not thread safe */
其次,您并不总是获得MaxDegreeOfParallelism
中要求的线程数。你永远不会得到更多,但你可能会得到更少。
如果您要使用并行性,请密切注意您将在线程中运行的代码的线程安全性。
答案 2 :(得分:0)
我认为你有两个主要原因没有获得50个帖子:
硬件。有一个点,处理器可以用更少的线程做更多的事情,因为切换线程所花费的时间不仅仅是更频繁地运行线程。这导致
托管代码。 C#.NET是一个托管代码系统。 .Net的程序员知道上面的内容,可能会设置一些限制和检查以防止太多的线程运行。您在代码中设置的内容可能高于某个内部限制,因此实际上会被忽略。此外,您正在设置最大值,因此Parallel.For()可以使用1到X个线程的任何位置,无论它认为哪个最有效。