并行功能,在C#中返回不同的结果
问题描述:
我在我的Windows窗体C#应用这些代码:并行功能,在C#中返回不同的结果
private void button7_Click(object sender, EventArgs e)
{
ThreadStart starter = delegate { thread_func(2, 1000000); };
thread1_thread = new Thread(starter);
starter = delegate { thread_func(1000000, 2000000); };
thread2_thread = new Thread(starter);
starter = delegate { thread_func(2000000, 3000000); };
thread3_thread = new Thread(starter);
starter = delegate { thread_func(3000000, 4000000); };
thread4_thread = new Thread(starter);
thread1_thread.Start();
thread2_thread.Start();
thread3_thread.Start();
thread4_thread.Start();
}
void thread_func(decimal input1,decimal input2)
{
for (; input1 < input2; input1++)
{
threadNumbers_list.Add(input1);
if (input1 % 2 != 0)
{
if (isPrime_func(input1))
{
PrimeNumbers_decimal_list.Add(input1);
}
}
}
}
public static Boolean isPrime_func(decimal number)
{
decimal boundary = (decimal)Math.Floor(Math.Sqrt((double)number));
if (number == 1) return false;
if (number == 2) return true;
for (decimal i = 2; i <= boundary; ++i)
{
if (number % i == 0) return false;
}
return true;
}
我每次运行单击该按钮,我得到不同的结果。我尝试了很多东西,但无法弄清楚为什么会发生这种情况。即使是在较低的范围内发生。例如,在100个数字的范围内,它总是给出相同的结果。 有些时候,我的清单计数达到283138,有时候是283131和其他接近的数字。
另一个奇怪的是,当我评论检查偶数时,操作比此模式花费的时间更短。怎么了?
答
当多个线程访问列表时,该列表必须是线程安全的,否则您将遇到很多问题。
.NET提供了一些类似ConcurrentQueue<T>
类的thread-safe collections。
附注:请考虑使用Tasks
而不是线程。此外,.NET框架supports data parallelism via the Parallel
class。考虑使用这样的类代替。
关于性能,当你不检查,如果数为偶数,我本地测试这一点,我得到了以下数字:
- 它需要〜76秒当我不,如果数量检查甚至。
- 当我检查数字是否均匀时,需要约66秒。
所以这与您的测量不符。这可能是由您测量的方式引起的。我有一个Stopwatch
这样测量:
//...
Stopwatch sw = Stopwatch.StartNew();
thread1_thread.Start();
thread2_thread.Start();
thread3_thread.Start();
thread4_thread.Start();
thread1_thread.Join();
thread2_thread.Join();
thread3_thread.Join();
thread4_thread.Join();
long result = sw.ElapsedMilliseconds;
//...
顺便说一句,这里的东西,你能做到这一点可能会节省一些执行时间为您提供:
创建为thread_func
内的每个线程正常List<T>
实例方法,以便您不会遇到多线程问题。然后在循环结束后,您可以从本地列表更新主列表。只更新主列表必须是线程安全的。在这种情况下,我宁愿主列表是正常的List<T>
,并且您使用lock
关键字来同步对它的访问,因为您只需要更新它4次(线程数)。
'threadNumbers_list'和'PrimeNumbers_decimal_list'可能不是线程安全的。 –
我创建该列表只是为了检查是否所有迭代都发生! – ACE
'PrimeNumbers_decimal_list'呢?另外,你如何等待线程完成?你使用'Thread.Join'吗? –