C# 简单素数程序-线程C的奇怪问题#
这是我的代码:C# 简单素数程序-线程C的奇怪问题#,c#,multithreading,algorithm,C#,Multithreading,Algorithm,这是我的代码: 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 bo
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);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
命名空间防火墙
{
班级计划
{
静态布尔[]线程完成;
静态bool[]nums;
静态布尔AllThreadsFinished()
{
bool-allThreadsFinished=false;
foreach(var threadFinished in ThreadsFinished)
{
所有螺纹精加工&=螺纹精加工;
}
返回所有已完成的线程;
}
静态bool isPrime(int n)
{
如果(n<2){返回false;}
如果(n==2){返回true;}
如果(n%2==0){返回false;}
int d=3;
而(d*d线程接收的值是线程运行时保持的值。要解决该问题,请将该值复制到局部变量中:
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();
}
有一个技巧可以帮助同步线程:您可以将所有线程保存在一个列表中,并从主线程连接它们
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();
}
var threads=newlist();
对于(int i=0;i
MarkPrimes(localStartNum,
Min(localStartNum+间隔,nrNums),i);
startNum=startNum+间隔;
_thread.IsBackground=true;
_thread.Start();
线程。添加(_线程);
}
foreach(线程中的var线程)
{
thread.Join();
}
只是一个快速的驱动器注释:而不是在AllThreadsFinished()时循环
为false,您应该在每个线程上一次调用一个,每次调用都将阻塞,直到相应的线程终止。这是等待线程完成的一种CPU效率更高的方法。Eratosthenes的筛选不能并行化:您有一个素数,您将它的所有倍数标记为非素数。您移动到下一个非marked number,打印出来,因为它是一个素数和重复数。两个独立的线程会做什么?@Cosmin Prund,这里说它可以,并给出了一个算法。我对这个问题没有太多研究,在学校里我只是以非并行方式实现它。我之所以提到它,是因为我知道它是最快的查找方法之一g素数。@Cosmin Prund通过线程之间的足够通信,您可以将其并行化,这样在筛选中标记倍数的每个线程总是在比读取素数的线程更高的数字上运行。在足够轻的并发性下,您可以对每个素数执行一个任务,并针对每个数字块周期性地唤醒它们,以供它们执行另一种选择是,因为从k开始的块的所有素数都小于sqrt(k),在不同的线程中处理块。@Para:你知道C#4.0中的新版本吗,它使你的手工簿记变得不必要了?@Para,你是对的,代码中存在另一个错误。AllThreadsFinished
总是计算为false。相应地更新答案。啊,是的,这样做了,谢谢。现在感觉很愚蠢。但是本地声明至少我们失踪了,这是个大错误。谢谢
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();
}