[英]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);
}
}
}
這應該是一個非常簡單的程序,應該使用並行工作的nrThreads
線程查找並輸出第一個nrNums
質數。
因此,我只是將nrNums
拆分為相等的nrThreads
塊(嗯,最后一個將不相等;如果nrThreads
不被nrNums
,那么它當然也將包含其余部分)。
我啟動nrThreads
線程。
他們都在各自的塊中測試每個數字,看是否為質數。 它們將所有內容標記在布爾數組中,從而使所有素數保持一致。
完成后,所有線程都將另一個布爾數組ThreadsFinished
的特定元素變為true。
現在,奇怪的部分開始了:
線程永遠不會結束。 如果調試,我發現ThreadNr
不是我在循環中為其分配的值,而是另一個值。 我猜這是正常的,因為線程是在之后執行的,此時計數器(變量i)已經增加,但是我不明白如何使代碼正確。
有人可以幫忙嗎?
先感謝您。
PS:我知道算法不是很有效; 我的目標是使用帶有x給定螺紋的Eratosthenes篩子的解決方案。 但是到目前為止,我什至無法使它工作,而且我還沒有找到任何能以我能理解的語言實現該算法的示例。
線程運行時,該線程接收的值是一個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();
}
代碼中的另一個錯誤正在等待所有線程:
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;
}
一個可以幫助同步線程的技巧:您可以將所有線程保存在列表中,然后從主線程加入它們。
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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.