Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run multiple threads at the same time without any running twice or failing

How can I run some threads at the same time without "running twice" or "failing" one of them? I will explain my question with an example:

private int count = 0;
private HashSet<int> hs_pages = new HashSet<int>();

for (int page = 1; page <= 10; page++)
{
    Thread thread = new Thread(unused => my_method(page));
    thread.Name = "Thread - " + page.ToString();
    thread.Start();
}
while(count < 10)
{

}

and my_method() is implemented as:

public void my_method(int page)
{
    if (hs_pages.Add(page))
    {    
           count++;
          //My Codes
    }
    else
    {
          MessageBox.Show("this is duplicate of page : " + page.ToString());
    }
}

after running this code I figured out some pages (1-10) don't run and some pages run twice.
so the while() never ends because of those duplicates and fails.

How can I fix those duplicates and failures?

My meaning of fail is not "Error", I mean for example my_method(4) never runs and my meaning of duplicate is for example my_method(3) runs twice.

I know there are other ways such as Parallel.ForEach, but I want to learn how to use the Thread Class.

like image 803
SilverLight Avatar asked Oct 11 '13 19:10

SilverLight


People also ask

Can we run 2 threads simultaneously?

Within a process or program, we can run multiple threads concurrently to improve the performance. Threads, unlike heavyweight process, are lightweight and run inside a single process – they share the same address space, the resources allocated and the environment of that process.

Can several instances of same thread can be opened and used at the same time?

Yes, A program can run two threads at the same time. it is called Multi threading. would they both be able to run at the same time or would my second function wait until the system call finishes?

Can a thread object be used to launch multiple threads?

Because Java threads run in the same memory space, they can easily communicate among themselves because an object in one thread can call a method in another thread without any overhead from the operating system. In this Tutorial we will learn how to do multi-threaded programming in Java.


1 Answers

You're closing over the loop variable.

Closures close over variables not over values. The lambda that you are creating isn't taking a copy of the current value of page within the body of the loop, it's creating a reference to that variable and it will access that variable's value when the anonymous method is actually executed at some point in the future. By the time that execution actually happens the loop has already continued on and incremented the value some number of times (we won't know how many; it'll depend on how the threads are scheduled).

Make a copy of page that's local to the body of the loop so that each closure is over a different variable, rather than a single variable that is being mutated:

for (int page = 1; page <= 10; page++)
{
    int pageCopy = page;
    Thread thread = new Thread(unused => my_method(pageCopy , count));
    thread.Name = "Thread - " + pageCopy.ToString();
    thread.Start();
}

Also, you shouldn't be doing a busy wait to wait for all of the threads to finish; that's extraordinarily wasteful of system resources to spend lots of CPU time spinning around in the while loop doing nothing. Instead put all of the Thread object that you create into a List<Thread> when you create them and then loop through the list again when you're done and call Join on them all to wait for them to finish.

like image 165
Servy Avatar answered Oct 14 '22 03:10

Servy