如果由线程执行的仿函数被移动会发生什么?

时间:2013-08-02 06:44:30

标签: c++ stl thread-safety functor

说我有一个类似

的仿函数
struct F
{
    // <some member variables go here>
    void operator()() { while(true) /*do stuff affecting the state*/; }
};

如果我创建了一个Fs矢量

std::vector<F> functorVec(10);

然后用这些仿函数启动一堆线程

for (int i = 0; i < functorVec.size(); ++i)
{
    boost::thread(functorVec[i]); 
}

现在我为我的矢量做了一些事情,比如

functorVec.push_back(F());

如果向量扩展并将其内容复制到新位置,是否会导致线程中出现未定义的行为?或者他们会崩溃吗?

似乎他们的状态已经发生了变化,可能是在他们正在进行某些操作的过程中。实际上,复制然后删除了完成工作的对象,对吗?由于移动与线程的执行是异步的,因此它似乎是坏消息。

我问,因为我希望能够保持每个运行自己的线程的对象集合。这些对象表示连接到系统的模块。我希望能够动态添加和分离模块。如果在集合中存储对象不是一个好主意,那么替代方案是什么?我是否必须在堆上分配它们并在我的集合中存储指针?

如果这根本不是问题,你能解释一下原因吗?

3 个答案:

答案 0 :(得分:3)

boost :: thread的构造函数按值接受仿函数:

template <class F> explicit thread(F f);

这意味着它会复制您提供的仿函数,因此id不会引用您在仿函数向量中的对象。因此,应该没有影响。

答案 1 :(得分:3)

reference

  

启动主题

     

通过传递可调用类型的对象来启动新线程   可以在没有参数的情况下调用构造函数。对象是   然后复制到内部存储中,并在新创建的上调用   执行的线程。如果不能(或不能)复制对象,   然后boost :: ref可用于传递对函数的引用   宾语。在这种情况下,Boost.Thread的用户必须确保   引用的对象比新创建的执行线程更长。

由于复制了线程参数,因此在启动所有线程后移动向量不会有问题。

答案 2 :(得分:3)

根据boost::thread documentation,您根本不需要存储仿函数。在构造时将复制可调用对象,并且永远不会再次引用您提供的原始文件。