Multithreading 在C+中实现boost::barrier+;11

Multithreading 在C+中实现boost::barrier+;11,multithreading,c++11,barrier,Multithreading,C++11,Barrier,我一直试图让一个项目摆脱所有boost引用,转而使用纯C++11 在某一点上,创建了线程工作线程,这些线程工作线程等待屏障发出“go”命令,完成工作(分布在N个线程中),并在所有线程完成时进行同步。基本思想是主循环给出go顺序(boost::barrier.wait())并使用相同的函数等待结果 我在另一个项目中实现了一个基于Boost版本的定制屏障,一切都很完美。实施情况如下: Barrier.h: class Barrier { public: Barrier(unsigned in

我一直试图让一个项目摆脱所有boost引用,转而使用纯C++11

在某一点上,创建了线程工作线程,这些线程工作线程等待屏障发出“go”命令,完成工作(分布在N个线程中),并在所有线程完成时进行同步。基本思想是主循环给出go顺序(boost::barrier.wait())并使用相同的函数等待结果

我在另一个项目中实现了一个基于Boost版本的定制屏障,一切都很完美。实施情况如下:

Barrier.h:

class Barrier {
public:
    Barrier(unsigned int n);
    void Wait(void);
private:
    std::mutex counterMutex;
    std::mutex waitMutex;

    unsigned int expectedN;
    unsigned int currentN;
};
Barrier.cpp

Barrier::Barrier(unsigned int n) {
    expectedN = n;
    currentN = expectedN;
}

void Barrier::Wait(void) {
    counterMutex.lock();

    // If we're the first thread, we want an extra lock at our disposal

    if (currentN == expectedN) {
        waitMutex.lock();
    }

    // Decrease thread counter

    --currentN;

    if (currentN == 0) {
        currentN = expectedN;
        waitMutex.unlock();

        currentN = expectedN;
        counterMutex.unlock();
    } else {
        counterMutex.unlock();

        waitMutex.lock();
        waitMutex.unlock();
    }
}
这段代码在iOS和Android的NDK上使用时没有任何问题,但在Visual Studio 2013项目上尝试时,似乎只有锁定互斥体的线程才能解锁它(断言:解锁无主互斥体)

是否有任何非旋转(阻塞,比如这个)版本的barrier可以用于C++11?我只能找到使用繁忙等待的障碍,这是我想要阻止的(除非确实没有原因)。

使用a而不是a来阻止所有线程,直到最后一个线程到达障碍

class Barrier
{
private:
    std::mutex _mutex;
    std::condition_variable _cv;
    std::size_t _count;
public:
    explicit Barrier(std::size_t count) : _count(count) { }
    void Wait()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        if (--_count == 0) {
            _cv.notify_all();
        } else {
            _cv.wait(lock, [this] { return _count == 0; });
        }
    }
};
等级壁垒
{
私人:
std::mutex\u mutex;
std::条件变量cv;
std::大小\u t\u计数;
公众:
显式屏障(std::size\u t count):\u count(count){
无效等待()
{
std::唯一的锁(互斥锁);
如果(--\u计数==0){
_cv.通知所有人();
}否则{
_wait(lock,[this]{return\u count==0;});
}
}
};
等级屏障{
公众:
显式屏障(标准::大小\u t i计数):
mThreshold(iCount),
mCount(iCount),
M生成(0){
}
无效等待(){
std::unique_lock lLock{mMutex};
自动lGen=M发电;
如果(!--mCount){
mggeneration++;
mCount=mThreshold;
mCond.notify_all();
}否则{
mCond.wait(lLock,[this,lGen]{return lGen!=mGeneration;});
}
}
私人:
std::互斥mMutex;
std::条件变量mCond;
标准:大小\u t阈值;
标准:尺寸/数量;
std::生成的大小;
};

这是我的版本,上面接受的答案具有自动重置行为,可重复使用;这是通过交替上下计数实现的

    /**
    * @brief Represents a CPU thread barrier
    * @note The barrier automatically resets after all threads are synced
    */
    class Barrier
    {
    private:
        std::mutex m_mutex;
        std::condition_variable m_cv;

        size_t m_count;
        const size_t m_initial;

        enum State : unsigned char {
            Up, Down
        };
        State m_state;

    public:
        explicit Barrier(std::size_t count) : m_count{ count }, m_initial{ count }, m_state{ State::Down } { }

        /// Blocks until all N threads reach here
        void Sync()
        {
            std::unique_lock<std::mutex> lock{ m_mutex };

            if (m_state == State::Down)
            {
                // Counting down the number of syncing threads
                if (--m_count == 0) {
                    m_state = State::Up;
                    m_cv.notify_all();
                }
                else {
                    m_cv.wait(lock, [this] { return m_state == State::Up; });
                }
            }

            else // (m_state == State::Up)
            {
                // Counting back up for Auto reset
                if (++m_count == m_initial) {
                    m_state = State::Down;
                    m_cv.notify_all();
                }
                else {
                    m_cv.wait(lock, [this] { return m_state == State::Down; });
                }
            }
        }
    };  
/**
*@brief表示CPU线程屏障
*@注意:所有线程同步后,屏障会自动重置
*/
阶级壁垒
{
私人:
std::mutex m_mutex;
std::条件变量m_cv;
大小和数量;
const size_t m_首字母;
枚举状态:无符号字符{
上下
};
州m_州;
公众:
显式屏障(std::size\u t count):m_count{count},m_initial{count},m_state{state::Down}
///阻塞,直到所有N个线程到达此处
void Sync()
{
std::unique_lock lock{m_mutex};
if(m_state==state::Down)
{
//正在倒计时同步线程的数量
如果(--m_计数==0){
m_state=state::Up;
m_cv.通知所有人();
}
否则{
m_cv.wait(lock,[this]{return m_state==state::Up;});
}
}
else/(m_state==state::Up)
{
//自动复位的倒计时
如果(++m_计数==m_初始值){
m_state=state::Down;
m_cv.通知所有人();
}
否则{
m_cv.wait(lock,[this]{return m_state==state::Down;});
}
}
}
};  

我喜欢这样一个事实,即它可以在几代人的时间内工作。这个实现是可重用的,并且不会出现虚假的唤醒。我相信这是一个拼写错误,应该是lLock(mMutex)而不是lLock{mMutex}。@jamshid不,这不是一个拼写错误,如果你想知道为什么
std::unique_lock
而不是
std::lock\u guard
,请看一下上面的示例,这是因为它是可重新锁定的。我们需要在等待条件变量时释放锁。请注意,此实现仅适用于一次性使用屏障,但不会出现虚假唤醒。假设我有三个线程需要等待屏障,并将屏障初始化为屏障(2);此代码似乎不起作用。是否使用
waitMutex
作为信号量?
    /**
    * @brief Represents a CPU thread barrier
    * @note The barrier automatically resets after all threads are synced
    */
    class Barrier
    {
    private:
        std::mutex m_mutex;
        std::condition_variable m_cv;

        size_t m_count;
        const size_t m_initial;

        enum State : unsigned char {
            Up, Down
        };
        State m_state;

    public:
        explicit Barrier(std::size_t count) : m_count{ count }, m_initial{ count }, m_state{ State::Down } { }

        /// Blocks until all N threads reach here
        void Sync()
        {
            std::unique_lock<std::mutex> lock{ m_mutex };

            if (m_state == State::Down)
            {
                // Counting down the number of syncing threads
                if (--m_count == 0) {
                    m_state = State::Up;
                    m_cv.notify_all();
                }
                else {
                    m_cv.wait(lock, [this] { return m_state == State::Up; });
                }
            }

            else // (m_state == State::Up)
            {
                // Counting back up for Auto reset
                if (++m_count == m_initial) {
                    m_state = State::Down;
                    m_cv.notify_all();
                }
                else {
                    m_cv.wait(lock, [this] { return m_state == State::Down; });
                }
            }
        }
    };