假设您希望并行运行一个节,然后合并回主线程,然后并行地返回到节,依此类推。类似于童年游戏的红灯绿灯。
我给出了一个我想要做的事情的例子,在这个例子中,我使用一个条件变量在开始时阻塞线程,但是希望并行地启动它们,但是在结束时阻止它们,这样就可以连续地输出它们。*=操作可能是一个跨越多秒的大得多的操作。重用线程也很重要。使用任务队列可能太重。
我需要使用某种阻塞结构,它不仅仅是一个普通的繁忙循环,因为我知道如何用繁忙的循环来解决这个问题。
英文本:
示例代码(从cplusplus.com上的示例改编而来):
// condition_variable example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <atomic>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
std::atomic<int> count(0);
bool end = false;
int a[10];
void doublea (int id) {
while(!end) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck);
a[id] *= 2;
count.fetch_add(1);
}
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();
ready = false; // Naive
while (count.load() < 10) sleep(1);
for(int i = 0; i < 10; i++) {
std::cout << a[i] << std::endl;
}
ready = true;
cv.notify_all();
ready = false;
while (count.load() < 10) sleep(1);
for(int i = 0; i < 10; i++) {
std::cout << a[i] << std::endl;
}
end = true;
cv.notify_all();
}
int main () {
std::thread threads[10];
// spawn 10 threads:
for (int i=0; i<10; ++i) {
a[i] = 0;
threads[i] = std::thread(doublea,i);
}
std::cout << "10 threads ready to race...\n";
go(); // go!
return 0;
}
发布于 2016-08-25 01:23:50
要有效地实现它,这并不是件简单的事情。此外,这是没有任何意义的,除非你正在学习这门学科。条件变量在这里不是一个很好的选择,因为它不能很好地扩展。
我建议您看看成熟的运行时库如何实现叉-连接并行,并向它们学习或在应用程序中使用它们。参见http://www.openmprtl.org/,http://opentbb.org/,https://www.cilkplus.org/ --所有这些都是开源的.
OpenMP是您所要寻找的最接近的模型,它具有最有效的叉-连接障碍实现。尽管如此,由于它是专为高性能计算机设计的,而且缺乏动态可组合性,因此也有其缺点。TBB和Cilk在模块和库中的嵌套并行性和使用效果最好,可以在外部并行区域的上下文中使用。
发布于 2016-08-24 06:41:34
您可以使用屏障或条件变量启动所有线程。然后,当所有线程结束其工作时(通过对所有线程的联接方法,线程是阻塞的),线程就可以等待,然后在一个循环中打印它们的数据。
https://stackoverflow.com/questions/39115581
复制相似问题