簡體   English   中英

在線程之間實現同步障礙的最佳方法是什么

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

在運行多個線程之后,我需要保證我的每個線程都會在繼續之前達到某個點。 我需要實施一種障礙。 考慮一個可以從多個線程運行的函數func

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

使用C ++ 11和VS12實現此障礙的最佳方法是什么,如果需要可以考慮增強。

你可以使用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();
}

每個線程等待直到滿足謂詞。 最后一個線程將使謂詞有效,並允許等待線程繼續。 如果要重用屏障(例如多次調用該函數),則需要另一個變量來重置計數器。

目前的實施是有限的。 一個調用func();func(); 兩次可能不會使線程第二次等待。

一個選項可以是使用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();
  }
}

使用-fopenmp編譯代碼

方案

#include <cassert>
#include <condition_variable>

class Barrier
{

public:

    Barrier(std::size_t nb_threads)
        : m_mutex(),
        m_condition(),
        m_nb_threads(nb_threads)
    {
        assert(0u != m_nb_threads);
    }

    Barrier(const Barrier& barrier) = delete;

    Barrier(Barrier&& barrier) = delete;

    ~Barrier() noexcept
    {
        assert(0u == m_nb_threads);
    }

    Barrier& operator=(const Barrier& barrier) = delete;

    Barrier& operator=(Barrier&& barrier) = delete;

    void Wait()
    {
        std::unique_lock< std::mutex > lock(m_mutex);

        assert(0u != m_nb_threads);

        if (0u == --m_nb_threads)
        {
            m_condition.notify_all();
        }
        else
        {
            m_condition.wait(lock, [this]() { return 0u == m_nb_threads; });
        }
    }

private:

    std::mutex m_mutex;

    std::condition_variable m_condition;

    std::size_t m_nb_threads;
};

示例

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

Barrier barrier(2u);

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

void func2()
{
    barrier.Wait();
    std::cout << "t2 awakened" << std::endl;
}

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

    return 0;
}

在線試用WandBox

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM