【发布时间】:2020-03-26 07:43:45
【问题描述】:
我正在尝试创建一个具有这样的构造函数的 ThreadPool 类
ThreadPool(size_t numberOfThreads)
: workerThreads(numberOfThreads) {
workerThreads.reserve(numberOfThreads);
for(int i =0; i < numberOfThreads; i++) {
workerThreads.emplace_back(std::thread(&ThreadPool::doJob, this));
}
}
这无法为我编译并引发以下错误
error: attempt to use a deleted function
__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/thread:352:5: note: in instantiation of function template specialization
'std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void
(ThreadPool::*)(std::__1::function<void (char *, std::__1::list<std::__1::basic_string<char>,
std::__1::allocator<std::__1::basic_string<char> > > *)>), ThreadPool *, 2>' requested here
__thread_execute(*__p, _Index());
根据类似问题的其他答案,我也尝试过这样做
workerThreads.emplace_back(std::thread(&ThreadPool::doJob, std::ref(*this)));
这也重现了同样的问题。我在 macos 上使用 clang c++14 编译我的代码
这是一个完整的程序,它再现了
class ThreadPool {
public:
ThreadPool(size_t numberOfThreads)
: workerThreads(numberOfThreads) {
for(int i =0; i < numberOfThreads; i++) {
workerThreads[i] = std::make_shared<std::thread>(std::thread(&ThreadPool::doJob, this));
}
}
ThreadPool(const ThreadPool& tp) {
workerThreads = tp.workerThreads;
jobQueue = tp.jobQueue;
}
std::function<void(char*, std::list<std::string>*)> getNextJob() {
if(!jobQueue.empty()) {
std::function<void(char*, std::list<std::string>*)> job = jobQueue.front();
jobQueue.pop_front();
return job;
}
throw std::runtime_error("No jobs to process, thread finished");
}
void addWork(std::function<void(char*, std::list<std::string>*)> job) {
lockListMutex.lock();
jobQueue.push_back(job);
lockListMutex.unlock();
}
private:
// performs actual work
void doJob(std::function<void(char*, std::list<std::string>*)> job) {
try {
lockListMutex.lock();
getNextJob();
lockListMutex.unlock();
} catch (std::runtime_error &e) {
}
}
// a vector containing worker threads
std::vector<std::shared_ptr<std::thread>> workerThreads;
// a queue for jobs
std::list<std::function<void(char*, std::list<std::string>*)>> jobQueue;
// a mutex for synchronized insertion and deletion from list
std::mutex lockListMutex;
};
int main(int argc, char *argv[]) {
int numThreads = 1;
ThreadPool* pool = new ThreadPool(numThreads);
}
【问题讨论】:
-
您使用的是哪种容器?如果它是一个向量,则假定底层类型(恰好是 std::thread)需要是可复制构造的,而这恰好是不允许被复制的。
-
是的,它是
std::vector -
您可以使用指针向量,因为允许复制 std::thread 指针。但是,在向量销毁时加入或分离所有线程将取决于您。
-
顺便说一句,在您的构造函数中,您正在创建
numberOfThreads * 2的线程。此外,您的“保留”没有任何意义,因为您已经实例化了一个相同大小的向量。它不会为您分配更多内存。并且重新放置会为您的向量添加两倍的元素。假设您使用可复制构造的类,则需要使用ThreadPool(size_t size) : workerThreads(size, std::thread(&ThreadPool::doJob, this)) {} -
我经常在 macOS 平台上使用
std::vector<std::thread>,并且已经使用了多年。我看到的唯一奇怪的事情是除了没有minimal reproducible example 的时间量是您的成员初始化列表中的workerThreads(size),这显然是错误的。workerThreads(size, std::thread(&ThreadPool::doJob, this))不会,这需要std::thread是可复制的,我们已经知道它不是(也不是可复制分配的)。但是,它应该是可移动的。
标签: c++ multithreading c++11 c++14