为什么以下屏障实施不起作用:
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。
这应该是一次性障碍吗?一旦 N 个线程遇到障碍,所有进一步的调用都是非阻塞的?在这种情况下,您需要一个布尔标志来指示已跳闸,并检查它。
问题是,如果
barrier()
被调用超过 NUM_THREAD
次,它将再次增加 barrier_count
,导致任何等待线程重新进入睡眠状态。
它适用于 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();
}
}