简单的素数程序 - 使用线程C#奇怪的问题 [英] Simple prime number program - Weird issue with threads C#
问题描述
这是我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace FirePrime
{
class Program
{
static bool[] ThreadsFinished;
static bool[] nums;
static bool AllThreadsFinished()
{
bool allThreadsFinished = false;
foreach (var threadFinished in ThreadsFinished)
{
allThreadsFinished &= threadFinished;
}
return allThreadsFinished;
}
static bool isPrime(int n)
{
if (n < 2) { return false; }
if (n == 2) { return true; }
if (n % 2 == 0) { return false; }
int d = 3;
while (d * d <= n)
{
if (n % d == 0) { return false; }
d += 2;
}
return true;
}
static void MarkPrimes(int startNumber,int stopNumber,int ThreadNr)
{
for (int j = startNumber; j < stopNumber; j++)
nums[j] = isPrime(j);
lock (typeof(Program))
{
ThreadsFinished[ThreadNr] = true;
}
}
static void Main(string[] args)
{
int nrNums = 100;
int nrThreads = 10;
//var threadStartNums = new List<int>();
ThreadsFinished = new bool[nrThreads];
nums = new bool[nrNums];
//var nums = new List<bool>();
nums[0] = false;
nums[1] = false;
for(int i=2;i<nrNums;i++)
nums[i] = true;
int interval = (int)(nrNums / nrThreads);
//threadStartNums.Add(2);
//int aux = firstStartNum;
//int i = 2;
//while (aux < interval)
//{
// aux = interval*i;
// i=i+1;
// threadStartNums.Add(aux);
//}
int startNum = 0;
for (int i = 0; i < nrThreads; i++)
{
var _thread = new System.Threading.Thread(() => MarkPrimes(startNum, Math.Min(startNum + interval, nrNums), i));
startNum = startNum + interval;
//set the thread to run in the background
_thread.IsBackground = true;
//start our thread
_thread.Start();
}
while (!AllThreadsFinished())
{
Thread.Sleep(1);
}
for (int i = 0; i < nrNums; i++)
if(nums[i])
Console.WriteLine(i);
}
}
}
这应该是一个非常简单的是应该找到并输出第一 nrNums
使用 nrThreads
并行工作线程素数的程序。
This should be a pretty simple program that is supposed to find and output the first nrNums
prime numbers using nrThreads
threads working in parallel.
所以,我就拆 nrNums
到 nrThreads
等于块(当然,最后一个将不等于;如果 nrThreads
不按 nrNums
分裂,它会还含有其余的,当然)。
So, I just split nrNums
into nrThreads
equal chunks (well, the last one won't be equal; if nrThreads
doesn't divide by nrNums
, it will also contain the remainder, of course).
我开始 nrThreads
线程。
他们都测试在各自的组块的每个号码,看看它是否是素数与否;他们在一个布尔数组保存的所有素数标签标注所有的东西。
They all test each number in their respective chunk and see if it is prime or not; they mark everything out in a bool array that keeps a tab on all the primes.
中的线程都打开一个特定的元素在另一个布尔数组 ThreadsFinished
为true,当他们完成。
The threads all turn a specific element in another boolean array ThreadsFinished
to true when they finish.
现在怪异的部分开始:
螺纹从来没有全部结束。如果我调试,我发现 ThreadNr
是不是我分配给它的循环,但另一个值。
我想这是正常的,因为线程执行后,计数器(变量i)已经上升到那时,但我不明白如何使代码是正确的。
The threads never all end. If I debug, I find that ThreadNr
is not what I assign to it in the loop but another value.
I guess this is normal since the threads execute afterwards and the counter (the variable i) is already increased by then but I cannot understand how to make the code be right.
谁能帮
感谢您提前
PS:我知道该算法是不是很有效;我使用埃拉托色尼的筛子也与给定的线程点¯x一个解决方案瞄准。但现在我甚至无法获得这一个工作,我没有找到我能理解的语言任何地方,算法的任何实现的任何实例。
P.S.: I know the algorithm is not very efficient; I am aiming at a solution using the sieve of Eratosthenes also with x given threads. But for now I can't even get this one to work and I haven't found any examples of any implementations of that algorithm anywhere in a language that I can understand.
推荐答案
该线程接收的值是一个 startNum
保存线程运行时。要解决它的值复制到一个局部变量:
The value the thread receives is the one startNum
holds when the thread runs. To solve it copy the value into a local variable:
for (int i = 0; i < nrThreads; i++)
{
var localStartNum = startNum; // save value in local variable
// and use in the thread start
var localIndex = i;
var _thread = new System.Threading.Thread(() =>
MarkPrimes(localStartNum,
Math.Min(localStartNum + interval, nrNums),
localIndex));
startNum = startNum + interval;
_thread.IsBackground = true;
_thread.Start();
}
在代码中的另一个错误是在等待所有线程:
Another bug in the code is waiting for all threads:
static bool AllThreadsFinished()
{
bool allThreadsFinished = true; // Initialize to true instead of false
// Otherwise, all ANDs will result false
foreach (var threadFinished in ThreadsFinished)
{
allThreadsFinished = threadFinished;
}
return allThreadsFinished;
}
一个技巧,可以帮助一点点的同步线程:您可以保存所有在列表中的线程和主线程加入他们的行列。
One tip which can help a little in synchronizing the threads: You can save all the threads in a list and join them from main thread.
var threads = new List<Thread>();
for (int i = 0; i < nrThreads; i++)
{
var localStartNum = startNum; // save value in local variable
// and use in the thread start
var _thread = new System.Threading.Thread(() =>
MarkPrimes(localStartNum,
Math.Min(localStartNum + interval, nrNums), i));
startNum = startNum + interval;
_thread.IsBackground = true;
_thread.Start();
threads.Add(_thread);
}
foreach(var thread in threads)
{
thread.Join();
}
这篇关于简单的素数程序 - 使用线程C#奇怪的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!