0

I had a bit of struggle to write a title to this... it seems like such a weird problem that should not occur!

This is my problem: I'm trying to make a program that uses 16 threads to calculate all the prime numbers between 0 and 16000000 as fast as possible, giving each thread a range of (0-16)=x*1000000 to (x+1)*1000000 to calculate all the primes using my function, prime(). So every thread does it's own million. Every time it finds a prime number it adds it to the array primes[].

Thread[] threads = new Thread[16];
ulong[] primes = new ulong[17000000];
ulong start, stop;
Thread t = new Thread(() => Console.ReadKey());
for (int i = 0; i < 16;)
{
    start = Convert.ToUInt64(i * 1000000);
    stop = Convert.ToUInt64((i + 1) * 1000000);

    threads[i] = new Thread(() =>
    {
        ulong start2 = start;
        ulong stop2 = stop;
                    
        Thread.Sleep(5000);
        for (ulong j = start2; j <= stop2; j++)
        {
            if (prime(j) == true)
            {
                primes[j] = j;
                total += 1;
            }
        }
        Console.WriteLine("another thread done calculating");
    });
    threads[i].Start();
    i++;

And then writing them into a file, however the problem is in the code above! it usually starts at 4000000, 3000000 or 2000000, when its supposed to start at 0, then work its way up to those higher numbers!

This is the whole program:

using System;
using System.Threading;
using System.IO;

namespace threading
{
    class Program
    {
        

        static bool prime(ulong primtal)
        {
            bool IsPrime = false;
            for (ulong i = 2; i <= (Convert.ToUInt64(Math.Sqrt(primtal))); i++)
            {

                if (primtal == 2 || primtal == 3)
                {
                    IsPrime = true;
                    break;
                }

                else if (primtal % i == 0)
                {
                    IsPrime = false;
                    break;
                }
                else
                {
                    IsPrime = true;
                }
            }
            return IsPrime;
        }

        static int total = 0, counter = 0;
        static void Main(string[] args)
        {

            Thread[] threads = new Thread[16];
            
            var timer = new Timer(TimerMethod, null, 0, 5000);
            ulong[] primes = new ulong[17000000];
            ulong start, stop;
            
            Thread t = new Thread(() => Console.ReadKey());
            for (int i = 0; i < 16;)
            {
                start = Convert.ToUInt64(i * 1000000);
                stop = Convert.ToUInt64((i + 1) * 1000000);

                threads[i] = new Thread(() =>
                {
                    ulong start2 = start;
                    ulong stop2 = stop;
                    
                    Thread.Sleep(5000);
                    for (ulong j = start2; j <= stop2; j++)
                    {
                        if (prime(j) == true)
                        {
                            primes[j] = j;
                            total += 1;
                        }
                    }
                    Console.WriteLine("another thread done calculating");
                });
                threads[i].Start();
                i++;
            }
            Console.ReadKey();
            StreamWriter SW = new StreamWriter("PATH");




            
            for (int f = 1; f < primes.Length; f++)
            {
                if (primes[f] != 0)
                {
                    SW.Write(f + " ");
                    counter += 1;
                }
                if (counter == 10)
                {
                    SW.Write("\n");
                    counter = 0;
                }
                
            }
            
            SW.Close();
            Console.WriteLine("Done! it should all be written into: \"PATH\"");
        }

        private static void TimerMethod(object o)
        {
            Console.WriteLine(total);
        }
    }
}

I'm on a windows 10 machine and I'm using the 3.1 dotnet framwork

How do I make it so thread 0 starts at 0 and then thread 1 starts at 1000000 and so on, like its supposed to?

AUniquee
  • 55
  • 6
  • Why do you care? They don't depend on each other and all of them need to finish, so order is completely irrelevant. And why do they have to sleep 5 secs? – Fildor Jan 18 '21 at 13:13
  • because I want to calculate all the prime numbers between the numbers and if I would want to make the program bigger this would be important, it's important that it does what it's supposed to! – AUniquee Jan 18 '21 at 13:16
  • So 0-1000000 does _not_ get computed _at all_? The snippet is not complete, by the way. Always try to post an [mcve], so we can reproduce the problem. And why do you inc `i` inside the loop? – Fildor Jan 18 '21 at 13:18
  • Oh sorry I'll include the whole program! – AUniquee Jan 18 '21 at 13:24
  • 3
    If you move the *declaration* of `start` and `stop` inside the loop, it should prevent this issue (and remove the need for `start2` and `stop2`, which I suspect was a first attempt to prevent the race). – Damien_The_Unbeliever Jan 18 '21 at 13:36
  • 2
    Also mind that you are accessing `total` and `counter` not thread-safely. – Fildor Jan 18 '21 at 13:39
  • 1
    `Thread t = new Thread(() => Console.ReadKey());` <== never used? – Fildor Jan 18 '21 at 13:41
  • And I'd use ParameterizedThreadstart to avoid any doubts about those values. – Fildor Jan 18 '21 at 13:43
  • 1
    And I am guessing your focus is on learning about threads rather than prime numbers. Because there is the [sieve of eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes). – Fildor Jan 18 '21 at 13:47
  • @Damien_The_Unbeliever when declaring them inside the loop, it fixes the issue but another one appears... or I dont even know if its a fix but it just calculates all the primes between 16000000-17000000 and thats it, any idea why that happens? – AUniquee Jan 18 '21 at 14:05

0 Answers0