Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to realize a synchronization barrier between threads

Having several threads running I need to guaranty that every of my threads reached a certain point before proceeding. I need to implement a kind of barrier. Consider a function func which can be run from several threads:

void func()
{
  operation1();
  // wait till all threads reached this point 
  operation2();
}

What is best way to realise this barrier using C++ 11 and VS12, considering boost if needed.

like image 473
GregPhil Avatar asked Aug 17 '16 14:08

GregPhil


People also ask

What is synchronization barrier in threads?

A synchronization barrier enables multiple threads to wait until all threads have all reached a particular point of execution before any thread continues. Synchronization barriers cannot be shared across processes.


2 Answers

You could use boost::barrier
Unfortunately, the thread barrier concept itself is not part of c++11 or visual c++.
In pure c++11 you could use a condition variable and a counter.

#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>

class my_barrier
{

 public:
    my_barrier(int count)
     : thread_count(count)
     , counter(0)
     , waiting(0)
    {}

    void wait()
    {
        //fence mechanism
        std::unique_lock<std::mutex> lk(m);
        ++counter;
        ++waiting;
        cv.wait(lk, [&]{return counter >= thread_count;});
        cv.notify_one();
        --waiting;
        if(waiting == 0)
        {
           //reset barrier
           counter = 0;
        }
        lk.unlock();
    }

 private:
      std::mutex m;
      std::condition_variable cv;
      int counter;
      int waiting;
      int thread_count;
};

int thread_waiting = 3;
my_barrier barrier(3);


void func1()
{
    std::this_thread::sleep_for(std::chrono::seconds(3));
    barrier.wait();
    std::cout << "I have awakened" << std::endl;
}

void func2()
{
    barrier.wait();
    std::cout << "He has awakened!!" << std::endl;
}

int main() {
    std::thread t1(func1);  
    std::thread t2(func2);
    std::thread t3(func2);
    t1.join();
    t2.join();
    t3.join();
}

Each thread wait till a predicate is met. The last thread will make the predicate valid, and allow the waiting threads to proceed. If you want to reuse the barrier (for instance call the function multiple times), you need another variable to reset the counter.

This current implementation is limited. A calling func();func(); twice may not make threads wait the second time.

like image 59
UmNyobe Avatar answered Dec 02 '22 00:12

UmNyobe


An option could be the use of OpenMP framework.

#include <omp.h>

void func()
{
  #pragma omp parallel num_threads(number_of_threads)
  {
    operation1();

    #pragma omp barrier
    // wait till all threads reached this point 

    operation2();
  }
}

Compile the code with -fopenmp

like image 26
tnas Avatar answered Dec 01 '22 23:12

tnas