How to sync "for" loop counter in multithread?

1.3k views Asked by At

How to sync "for" loop counter on multithread?

If these multi thread program

void Func(int n){
 for(int i=0; i<n; i++){ //at the same time with other Func()
  cout << i <<endl;
 }
}

void main(){
 std::thread t1(Func(2));
 std::thread t2(Func(2));
 t1.join();
 t2.join();
}

When executing Func() in parallel , I want to sync "for" loop counter "i".

For example, the program has possibility to output the result

0
1
0
1

but I want to always get the result

0
0
1
1

Can I it?

3

There are 3 answers

0
Ami Tavory On BEST ANSWER

One way to do it would be to use a few variables for the threads to coordinate things (in the following they are globals, just for simplicity).

mutex m;
condition_variable c;
static int index = 0;
static int count = 2;

The index variable says at which index are the threads, and the count variable says how many threads are at the index still.

Now you're loop becomes:

void Func(int n){
 for(int i=0; i<n; i++){ //at the same time with other Func()
    unique_lock<mutex> l(m);
    c.wait(l, [i](){return index == i;});
    cout << i <<endl;
    if(--count == 0)
    {
        ++index;
        count = 2;
        c.notify_one();
    }
 }
}

Here is the full code:

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>


using namespace std;


mutex m;
condition_variable c;
static int index = 0;
static int count = 2;


void Func(int n){
 for(int i=0; i<n; i++){ //at the same time with other Func()
    unique_lock<mutex> l(m);
    c.wait(l, [i](){return index == i;});
    cout << i <<endl;
    if(--count == 0)
    {
        ++index;
        count = 2;
        c.notify_one();
    }
 }
}


int main(){
 std::thread t1(Func, 20);
 std::thread t2(Func, 20);
 t1.join();
 t2.join();
}
0
RyanP On

If you use OpenMP to thread your loop you can use a #pragma omp barrier statement.

In C++11 you can use a condition_variable to block all threads until they reach the same spot.

0
NathanOliver On

You can use a std:atomic variable and pass it to all threads.

void Func(int n, int & i){
    for (; i<n; i++){ //at the same time with other Func()
        cout << i << endl;
    }
}

void main(){
    std::atomic<int> counter = 0;
    std::thread t1(Func, 2, std::ref(counter));
    std::thread t2(Func, 2, std::ref(counter));
    t1.join();
    t2.join();
}

Also you should note that the way you are crating your threads in your example are incorrect. Secondly if you are using cout in multiple threads each cout should be guarded with a std::mutex as cout is not thread safe.