【发布时间】:2018-08-03 23:28:25
【问题描述】:
我有许多作业,我想并行运行其中的一部分。例如。我有 100 个作业要运行,我想一次运行 10 个线程。这是我当前解决此问题的代码:
#include <thread>
#include <vector>
#include <iostream>
#include <atomic>
#include <random>
#include <mutex>
int main() {
constexpr std::size_t NUMBER_OF_THREADS(10);
std::atomic<std::size_t> numberOfRunningJobs(0);
std::vector<std::thread> threads;
std::mutex maxThreadsMutex;
std::mutex writeMutex;
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0, 2);
for (std::size_t id(0); id < 100; ++id) {
if (numberOfRunningJobs >= NUMBER_OF_THREADS - 1) {
maxThreadsMutex.lock();
}
++numberOfRunningJobs;
threads.emplace_back([id, &numberOfRunningJobs, &maxThreadsMutex, &writeMutex, &distribution, &generator]() {
auto waitSeconds(distribution(generator));
std::this_thread::sleep_for(std::chrono::seconds(waitSeconds));
writeMutex.lock();
std::cout << id << " " << waitSeconds << std::endl;
writeMutex.unlock();
--numberOfRunningJobs;
maxThreadsMutex.unlock();
});
}
for (auto &thread : threads) {
thread.join();
}
return 0;
}
在 for 循环中,我检查有多少作业正在运行,如果一个插槽空闲,我将一个新线程添加到向量中。在每个线程结束时,我会减少正在运行的作业数量并解锁互斥锁以启动一个新线程。这解决了我的任务,但有一点我不喜欢。我需要一个大小为 100 的向量来存储所有线程,并且我需要在最后加入所有 100 个线程。我想在完成后从向量中删除每个线程,以便向量包含最多 10 个线程,并且我必须在最后加入 10 个线程。我考虑通过引用 lambda 来传递向量和迭代器,以便我可以在最后删除元素,但我不知道如何。如何优化我的代码以在向量中使用最多 10 个元素?
【问题讨论】:
-
考虑建立一个线程池并重用现有线程。
-
请注意,在锁定
maxThreadsMutex时解锁会产生未定义的行为 -
为什么要保留所有线程?由于您不重复使用,我认为您可以简单地将其分离并等待一些完成信号。
-
或者你可以简单地等待最后 10 个线程。
-
@LWimsey:你的意思是在未锁定的情况下解锁?
标签: c++ multithreading c++11