gpt4 book ai didi

c# - 简单的素数程序 - 线程 C# 的奇怪问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:34:42 40 4
gpt4 key购买 nike

这是我的代码:

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 相等的 block (好吧,最后一个不相等;如果 nrThreads 不相等' t 除以 nrNums,当然它也会包含余数)。

我启动了 nrThreads 个线程。

他们都测试各自 block 中的每个数字,看看它是否是质数;他们在一个 bool 数组中标记所有内容,该数组在所有素数上都有一个标签。

线程在完成时将另一个 bool 数组 ThreadsFinished 中的特定元素全部变为 true。

现在奇怪的部分开始了:

线程永远不会结束。如果我调试,我发现 ThreadNr 不是我在循环中分配给它的值,而是另一个值。我想这是正常的,因为线程随后执行并且计数器(变量 i)已经增加,但我不明白如何使代码正确。

有人能帮忙吗?

提前谢谢你。

P.S.:我知道这个算法不是很有效;我的目标是使用 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();
}

代码中的另一个错误是等待所有线程:

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();
}

关于c# - 简单的素数程序 - 线程 C# 的奇怪问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4574742/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com