在线程之间实现同步障碍的最佳方法是什么

Gre*_*hil 8 c++ multithreading c++11

在运行多个线程之后,我需要保证我的每个线程都会在继续之前达到某个点.我需要实施一种障碍.考虑一个func可以从多个线程运行的函数:

void func()
{
  operation1();
  // wait till all threads reached this point 
  operation2();
}
Run Code Online (Sandbox Code Playgroud)

使用C++ 11和VS12实现此障碍的最佳方法是什么,如果需要,考虑增强.

UmN*_*obe 10

你可以使用boost :: barrier
不幸的是,线程屏障概念本身不是c ++ 11或visual c ++的一部分.
在纯c ++ 11中,您可以使用条件变量和计数器.

#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();
}
Run Code Online (Sandbox Code Playgroud)

每个线程等待直到满足谓词.最后一个线程将使谓词有效,并允许等待线程继续.如果要重用屏障(例如多次调用该函数),则需要另一个变量来重置计数器.

目前的实施是有限的.调用func();func();两次可能不会使线程第二次等待.

  • 用您的`wait`实现示例;想象一下2个线程的障碍-它们都调用`wait`,调用等待第二个计数的线程将会取得进展。但是由于调用“ wait”等待第一个计数的线程永远不会被唤醒(“ notified”),因此从理论上讲它可能永远等待。 (3认同)

小智 3

一种选择是使用 OpenMP 框架。

#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();
  }
}
Run Code Online (Sandbox Code Playgroud)

使用 -fopenmp 编译代码