为什么这个 C++ 屏障实现不起作用?

问题描述 投票:0回答:2

为什么以下屏障实施不起作用:

void JoinQuery::barrier() {
    std::unique_lock<std::mutex> lk(barrier_mutex);
    barrier_count++;
    if (barrier_count == NUM_THREADS) {
        barrier_count = 0;
        lk.unlock();
        barrier_cv.notify_all();
    } else {
        barrier_cv.wait(lk, [this] { return barrier_count == 0; });
    }
}

但是,如果我使用第二个变量来跟踪所有线程到达的条件,它就会起作用。

但我不知道为什么这是必要的。在所有线程到达之前,线程应该不可能看到barrier_count == 0。

c++ multithreading mutex condition-variable barrier
2个回答
0
投票

这应该是一次性障碍吗?一旦 N 个线程遇到障碍,所有进一步的调用都是非阻塞的?在这种情况下,您需要一个布尔标志来指示已跳闸,并检查它。

问题是,如果

barrier()
被调用超过
NUM_THREAD
次,它将再次增加
barrier_count
,导致任何等待线程重新进入睡眠状态。


0
投票

它适用于 1000 个线程

#include <vector>
#include <thread>
#include <condition_variable>
using namespace std;

int NUM_THREADS = 1000;

class JoinQuery {
    mutex               barrier_mutex;
    condition_variable  barrier_cv;
    int barrier_count = 0;
public:
    void barrier(int num) {
        std::unique_lock<std::mutex> lk(barrier_mutex);
        barrier_count++;
        if (barrier_count == NUM_THREADS) {
            barrier_count = 0;
            barrier_cv.notify_all();
        } else {
            barrier_cv.wait(lk, [this] { return barrier_count == 0; });
            printf("wake num=%d\n", num);
        }
    }
};

int main(){
    JoinQuery       jq;
    vector<thread>  ts;
    for (int i = 0; i < NUM_THREADS; i++) {
        ts.push_back(thread(&JoinQuery::barrier, ref(jq), i));
    }
    for (auto& t : ts) {
        t.join();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.