我正在用 C++ 编程,但我只使用 pthread.h,没有 boost 或 C++11 线程。
所以我正在尝试使用线程,但基于我之前的一个问题(链接),这似乎不可行,因为线程在完成其任务后立即终止,这是使用线程池实现的更普遍的原因之一是通过将这些线程重用于多个任务来减少线程创建开销。
那么在 C 中实现这一点的唯一其他方法是使用 fork(),并创建从主进程到子进程的管道?或者有没有办法在我不知道的线程和它们的父级之间建立一个管道?
提前谢谢了!
我正在用 C++ 编程,但我只使用 pthread.h,没有 boost 或 C++11 线程。
所以我正在尝试使用线程,但基于我之前的一个问题(链接),这似乎不可行,因为线程在完成其任务后立即终止,这是使用线程池实现的更普遍的原因之一是通过将这些线程重用于多个任务来减少线程创建开销。
那么在 C 中实现这一点的唯一其他方法是使用 fork(),并创建从主进程到子进程的管道?或者有没有办法在我不知道的线程和它们的父级之间建立一个管道?
提前谢谢了!
是的,您可以在线程之间创建线程安全队列。然后池中的线程将坐在一个循环中,从队列中检索一个项目,执行它需要的任何内容,然后返回并获取另一个。
这在 C++ 中通常更容易/更简单,因为在某些接口上达成一致更容易一些(例如,重载operator()
以执行任务的代码),但从根本上讲,您可以在 C 中做所有相同的事情(例如,您放入队列中的每个task
结构都将包含一个指向执行该任务工作的函数的指针)。
在您的情况下,由于您使用的是 C++,因此使用重载 of 可能更容易operator()
完成这项工作。结构的其余部分task
(或您选择的任何名称)将包含所需的任何数据等。
从POSIX 标准:
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
(...) 线程被创建为它的唯一参数
start_routine
执行。arg
所以,你应该用这个函数创建一堆线程,并让它们都执行一个类似的函数
void *consumer(void *arg)
{
WorkQueue *queue = static_cast<WorkQueue *>(arg);
for (task in queue) {
if (task == STOP_WORKING)
break;
do work;
}
return WHATEVER;
}
(在输入结束时,将n 个 STOP_WORKING
项目推送到队列中,其中n是线程数。)
请注意,pthreads 是一个非常低级的 API,它提供的类型安全性非常低(所有数据都作为void
指针传递)。如果您尝试并行化 CPU 密集型任务,则可能需要查看OpenMP。
'似乎不可行,因为线程在完成任务后立即终止'什么?
for(;;){
Task *myTask=theCommonProducerConsumerQueue->pop();
myTask->run();
}
..永远不要返回任何东西,事实上,永远不要返回。
您可能会发现查看libdispatch 的源代码很有帮助,它是 Apple 的 Grand Central Dispatch 的基础并使用线程池。
我建议使用英特尔的线程构建块来完成类似工作队列/线程池的任务。使用 TBB 3.0 的一个相当人为的示例:
class PoorExampleTask : public tbb::task {
PoorExampleTask(int foo, tbb::concurrent_queue<float>& results)
: _bar(foo), _results(results)
{ }
tbb::task* execute() {
_results.push(pow(2.0, foo));
return NULL;
}
private:
int _bar;
tbb::concurrent_queue<float>& _results;
}
以后像这样使用:
tbb::concurrent_queue<float> powers;
for (int ww = 0; ww < LotsOfWork; ++ww) {
PoorExampleTask* tt
= new (tbb::task::allocate_root()) PoorExampleTask(ww, powers);
tbb::task::enqueue(*tt);
}
几个月前我用过谷歌,你应该试试。
编辑:看来您可能想要一个小组。我能够创建一个对上述内容进行一些小的改动,以便工人不执行工作,而只是加入线程。