Par*_*ara 2 c# algorithm multithreading
这是我的代码:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这应该是一个非常简单的程序,应该nrNums
使用nrThreads
并行工作的线程来查找和输出第一个素数.
所以,我只是分裂nrNums
成nrThreads
相等的块(当然,最后一个是不相等的;如果nrThreads
不被分裂nrNums
,它还将包含课程的其余部分).
我开始nrThreads
线程.
他们都在各自的块中测试每个数字,看看它是否是素数; 它们在bool数组中标记所有内容,并在所有素数上保留一个标签.
这些线程在ThreadsFinished
完成时都会将另一个布尔数组中的特定元素转换为true.
现在奇怪的部分开始了:
线程永远都不会结束.如果我调试,我发现这ThreadNr
不是我在循环中分配给它的另一个值.我想这是正常的,因为线程后来执行并且计数器(变量i)已经增加,但我无法理解如何使代码正确.
有人可以帮忙吗?
先感谢您.
PS:我知道算法效率不高; 我的目标是使用Eratosthenes的筛子和x给定的螺纹.但是现在我甚至无法让这个工作起来,我也没有找到任何在我能理解的语言中任何实现该算法的例子.
线程接收的值是startNum
线程运行时保存的值.要解决它,请将值复制到局部变量中:
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();
}
Run Code Online (Sandbox Code Playgroud)
代码中的另一个错误是等待所有线程:
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;
}
Run Code Online (Sandbox Code Playgroud)
一个可以帮助一点同步线程的提示:您可以保存列表中的所有线程并从主线程连接它们.
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();
}
Run Code Online (Sandbox Code Playgroud)