有关问题:
关于C 11:
关于升压:
我如何获得发送任务的线程池,而不必一次又一次地创建和删除它们?这意味着持久性线程可以在不加入的情况下重新同步。
我有如下代码:
namespace {
std::vector<std::thread> workers;
int total = 4;
int arr[4] = {0};
void each_thread_does(int i) {
arr[i] += 2;
}
}
int main(int argc, char *argv[]) {
for (int i = 0; i < 8; ++i) { // for 8 iterations,
for (int j = 0; j < 4; ++j) {
workers.push_back(std::thread(each_thread_does, j));
}
for (std::thread &t: workers) {
if (t.joinable()) {
t.join();
}
}
arr[4] = std::min_element(arr, arr+4);
}
return 0;
}
与每次迭代都创建和加入线程不同,我更愿意在每次迭代中将任务发送给我的工作线程,并且只创建一次。
线程池意味着所有线程都在运行,也就是说,线程函数永远不会返回。为了给线程一些有意义的事情去做,您必须设计一个线程间通信系统,既可以告诉线程有事情要做,也可以通信实际的工作数据。
通常,这将涉及某种并发数据结构,每个线程可能会在某种条件变量上Hibernate,当有工作要做时,会通知这些条件变量。收到通知后,一个或多个线程将唤醒,从并发数据结构中恢复任务,对其进行处理,并以类似的方式存储结果。
然后,线程会继续检查是否有更多的工作要做,如果没有,就继续睡觉。
结果是你必须自己设计所有这些,因为没有一个普遍适用的“工作”的自然概念。这是相当多的工作,有些微妙的问题你必须解决。(如果你喜欢一个在幕后为你处理线程管理的系统,你可以在Go中编程。)
您可以使用C线程池库,https://github.com/vit-vit/ctpl.
然后您编写的代码可以替换为以下代码
#include <ctpl.h> // or <ctpl_stl.h> if ou do not have Boost library
int main (int argc, char *argv[]) {
ctpl::thread_pool p(2 /* two threads in the pool */);
int arr[4] = {0};
std::vector<std::future<void>> results(4);
for (int i = 0; i < 8; ++i) { // for 8 iterations,
for (int j = 0; j < 4; ++j) {
results[j] = p.push([&arr, j](int){ arr[j] +=2; });
}
for (int j = 0; j < 4; ++j) {
results[j].get();
}
arr[4] = std::min_element(arr, arr + 4);
}
}
您将获得所需的线程数,并且不会在迭代中一遍又一遍地创建和删除它们。
这是从我的回答复制到另一个非常类似的帖子:
>
从系统可以支持的最大线程数开始:
int num_threads = std::thread::hardware_concurrency();
为了实现高效的线程池,一旦根据num_threads
创建了线程,最好不要创建新线程,也不要破坏旧线程(通过加入)。这将导致性能下降,甚至可能使应用程序运行速度比串行版本慢。
每个C11线程应该以无限循环的方式在其函数中运行,不断等待新任务的抓取和运行。
下面是如何将这样一个函数附加到线程池:
int num_threads = std::thread::hardware_concurrency();
std::vector<std::thread> threads;
for (int i = 0; i < num_threads; i++)
{
pool.push_back(std::thread(Infinite_loop_function));
}
void Pool::Infinite_loop_function()
{
while (true)
{
{
std::unique_lock<std::mutex> lock(queue_mutex);
condition.wait(lock, [this](){
return !queue.empty() || terminate_pool;
});
Job = queue.front();
queue.pop();
}
Job(); // function<void()> type
}
};
void Pool::Add_Job(function<void()> New_Job)
{
{
std::unique_lock<std::mutex> lock(queue_mutex);
queue.push(New_Job);
}
condition.notify_one();
}
Pool_Obj.Add_Job(std::bind(&Some_Class::Some_Method, &Some_object));
一旦您集成了这些成分,您就拥有了自己的动态线程池。这些线程总是运行,等待作业完成。
如果有一些语法错误,我道歉,我打了这个代码,我有一个坏的记忆。很抱歉,我不能提供完整的线程池代码;这将违反我的工作完整性。
编辑:要终止池,请调用Shutdown()
方法:
Pool::shutdown()
{
{
std::unique_lock<std::mutex> lock(threadpool_mutex);
terminate_pool = true; // use this flag in condition.wait
}
condition.notify_all(); // wake up all threads.
// Join all threads.
for (std::thread &th : threads)
{
th.join();
}
pool.clear();
stopped = true; // use this flag in destructor, if not set, call shutdown()
}
我对最新gcc中基于pthread和Ubuntu开发环境的线程的互斥锁和消息传递的性能感兴趣。一个很好的通用问题是用餐哲学家,每个哲学家使用lh和rh叉子与左右手邻居共享。我把哲学家的数量增加到99个,让我的四核处理器保持忙碌。 上面的代码允许我的哲学家尝试抓住他们需要的两个叉子。 上面的代码监控我的哲学家的进食或思考进度,这取决于他们是否能够保留这两个叉子。 在所有哲学家尝试自由选择后,等待所有
我在Ubuntu13.04桌面上运行这个非常简单的程序,但是如果我注释掉sleep_for一行,它会在从main打印cout后挂起。有人能解释为什么吗?据我所知,main是一个线程,t是另一个线程,在本例中,互斥体管理共享cout对象的同步。
如何从线程池中找到60%(或N%)的线程可用性?这背后的逻辑是什么? 父线程使用线程池线程生成多个网址,并等待所有子线程完成。 代码如下所示 父线程 子线程 用于跨线程通信的对象数据 在上述代码中,所需的线程硬编码为: 这种硬编码会导致线程池不足吗?如果线程池中没有可用的线程,会发生什么?如何在托管服务器的线程池中查找可用线程的总数? 谢谢。
本文向大家介绍详解python中的线程与线程池,包括了详解python中的线程与线程池的使用技巧和注意事项,需要的朋友参考一下 线程 进程和线程 什么是进程? 进程就是正在运行的程序, 一个任务就是一个进程, 进程的主要工作是管理资源, 而不是实现功能 什么是线程? 线程的主要工作是去实现功能, 比如执行计算. 线程和进程的关系就像员工与老板的关系, 老板(进程) 提供资源 和 工作空间, 员工(
如果我有一个固定大小的线程池,它什么时候真正调用启动线程?(它会在创建时启动它们吗?还是等到我开始提交任务时再启动?)
本文向大家介绍C#线程处理系列之线程池中的I/O线程,包括了C#线程处理系列之线程池中的I/O线程的使用技巧和注意事项,需要的朋友参考一下 一、I/O线程实现对文件的异步 1.1 I/O线程介绍: 对于线程所执行的任务来说,可以把线程分为两种类型:工作者线程和I/O线程。 工作者线程用来完成一些计算的任务,在任务执行的过程中,需要CPU不间断地处理,所以,在工作者线程的执行过程中,CPU和线程
我找到了关于线程安全的代码,但它没有来自给出示例的人的任何解释。我想知道为什么如果我不在“count”之前设置“synchronized”变量,那么count值将是非原子的(总是=200是期望的结果)。谢谢