我用这个测试程序在我的虚拟 linux 机器 (GCC 4.4.5-Debian) 中随机测试 std::thread
:
#include <algorithm>
#include <thread>
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
static int i=0;
void f( vector<int> &test)
{
++i;
cout << "Push back called" << endl;
test.push_back(i);
}
int main()
{
vector<thread> t;
vector<int> test;
for( int i=0; i<1000; ++i )
{
t.push_back( thread( bind(f, test) ) );
}
for( auto it = t.begin(); it != t.end(); ++it )
{
(*it).join();
}
cout << test.size() << endl;
for( auto it = test.begin(); it != test.end(); ++it )
{
cout << *it << endl;
}
return 0;
}
为什么 vector test
保持为空?我是在用引用做一些愚蠢的事情(可能)还是用 bind
或一些线程问题?
谢谢!
更新:在 Kos 和 villintehaspan 的共同帮助下,我“解决”了“问题”:
#include <algorithm>
#include <thread>
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
static int i=0;
void f( vector<int> &test)
{
++i;
test.push_back(i);
}
int main()
{
vector<thread> t;
vector<int> test;
for( int i=0; i<1000; ++i )
{
t.push_back( thread(f, std::ref(test)) );
}
for( auto it = t.begin(); it != t.end(); ++it )
{
(*it).join();
}
cout << test.size() << endl;
for( auto it = test.begin(); it != test.end(); ++it )
{
cout << *it << endl;
}
return 0;
}
它按顺序打印所有值并且似乎工作正常。现在只剩下一个问题:这只是幸运(又名未定义行为 (TM))还是静态变量在代码中导致类似互斥锁的静默步骤?
PS:我理解这里的“杀死多线程”问题,但这不是我的意思。我只是想测试基本 std::thread
功能的稳健性...
最佳答案
在我看来像是线程问题。
虽然我不是 100% 确定,但应该注意所有 1000 个线程:
做
++i
在相同的 int 值上(这不是原子操作 - 你可能会在这里遇到问题,你可以使用__sync_fetch_and_add(&i,1)
代替(注意它是 gcc 扩展而不是标准 C++);做
push_back
同时在std::vector
上,这不是线程安全的容器 AFAIK... 与cout
相同我认为。我相信您需要围绕它使用锁定机制(可能是std::mutex
?到目前为止我只使用过 pthread,但我相信这是您所需要的)。
请注意,这种情况会扼杀在这里使用线程的任何好处,但这是因为您不应该在非线程安全对象上同时使用多个线程这一事实。
----编辑----
我在谷歌上搜索了这个线程 API(不幸的是,我的 Windows 上的 tdm gcc 4.5 上没有)。 显然不是:
thread( bind(f, test) )
你可以说
thread( f, test )
并以这种方式传递任意数量的参数。
来源:http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=422
这也应该可以解决您制作 vector 拷贝的问题,我之前没有注意到
(这里为@villintehaspam +1)。
实际上,还需要做一件事来确保不会在此处创建拷贝:
thread( f, std::ref(test) )
将确保 vector 未被复制。
哇,我也糊涂了。 :)
关于c++ - 关于函数引用和线程的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4578474/