c++ - 关于函数引用和线程的问题

标签 c++ multithreading c++11 reference bind

我用这个测试程序在我的虚拟 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/

相关文章:

c++ - 为 C++ 构建 Lua

c# - 如何在条件语句中使用 Linq 的 .Count() 方法

java - 使用java.util.Timer监控java中的2个线程,它们基于计时相互依赖

c++ - C++原子compare_exchange_weak

c++ - 初始化嵌套 vector 的大小

c++ - 确保模板参数是枚举类

c++ - cmake 链接 xlib 目录 C++

使用标准输入和标准输出的 C++ 可变大小数组

c++ - 检查原始文件 C++ 的输出

multithreading - Oracle sqlldr是否并行处理多个INFILE