使用std :: thread多线程无法正常工作(C ++ 11)

时间:2013-07-02 16:53:31

标签: c++ multithreading c++11 stdthread

我编写了一个小型c ++程序,试图了解多线程如何使用std::thread。这是程序执行的步骤:

  1. 初始化5x5整数矩阵,其中包含“Toto”类中的唯一值“42”(在主要内容中初始化)。
  2. 我打印初始化的5x5矩阵。
  3. 声明std::vector 5个帖子。
  4. 我分别使用其任务(threadTask方法)附加所有线程。每个线程都将操作std::vector<int>实例。
  5. 我加入所有主题。
  6. 我打印出5x5矩阵的新状态。
  7. 这是输出:

    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    
    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    

    应该是:

    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    42 42 42 42 42
    
    0 0 0 0 0
    1 1 1 1 1
    2 2 2 2 2
    3 3 3 3 3
    4 4 4 4 4
    

    以下是代码示例:

    #include <iostream>
    #include <vector>
    #include <thread>
    
    class       Toto
    {
    public:
        /*
        ** Initialize a 5x5 matrix with the 42 value.
        */
        void    initData(void)
        {
            for (int y = 0; y < 5; y++) {
                std::vector<int> vec;
    
                for (int x = 0; x < 5; x++) {
                    vec.push_back(42);
                }
                this->m_data.push_back(vec);
            }
        }
    
        /*
        ** Display the whole matrix.
        */
        void    printData(void) const
        {
            for (int y = 0; y < 5; y++) {
                for (int x = 0; x < 5; x++) {
                    printf("%d ", this->m_data[y][x]);
                }
                printf("\n");
            }
            printf("\n");
        }
    
        /*
        ** Function attached to the thread (thread task).
        ** Replace the original '42' value by the another one.
        */
        void    threadTask(std::vector<int> &list, int value)
        {
            for (int x = 0; x < 5; x++) {
                list[x] = value;
            }
        }
    
        /*
        ** Return a sub vector reference according to the range.
        */
    
        std::vector<int>    &getDataByRange(int range)
        {
            return (this->m_data[range]);
        }
    
        private:
            std::vector<std::vector<int> > m_data;
    };
    
    int         main(void)
    {
        Toto    toto;
    
        toto.initData();
    
        toto.printData(); //Display the original 5x5 matrix (first display).
    
        std::vector<std::thread> threadList(5); //Initialization of vector of 5 threads.
    
        for (int i = 0; i < 5; i++) {  //Threads initializationss
    
            std::vector<int> &vec = toto.getDataByRange(i); //Get each sub-vectors reference.
            threadList.at(i) = std::thread(&Toto::threadTask, toto, vec, i); //Each thread will be attached to a specific vector.
        }
    
        for (int j = 0; j < 5; j++) {
            threadList.at(j).join();
        }
    
        toto.printData(); //Second display.
        getchar();
    
        return (0);
    }
    

    但是,在方法threadTask中,如果我打印变量list[x],则输出正确。我认为我无法在main中打印正确的数据,因为printData()调用在主线程中并且threadTask函数中的显示是正确的,因为该方法是在自己的线程中执行的(不是主线程)一)。奇怪的是,这意味着在父进程中创建的所有线程都无法修改此父进程中的数据?我想我忘记了代码中的一些东西。我真的迷路了。有人能帮帮我吗? 非常感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

在我看来,你在写这篇文章时做出的许多选择都使你的工作变得非常困难。特别是,你的toto类似乎(对我来说)使客户端代码更复杂而不是更简单,并且无法封装它操作的数据。我想如果我要这样做,我会在这些一般的路线上编写代码:

#include <iostream>
#include <vector>
#include <thread>
#include <algorithm>

std::ostream &operator<<(std::ostream &os, std::vector<int> const &d) {
    for (auto const &v : d)
        os << v << "\t";
    return os;
}

std::ostream &operator<<(std::ostream &os, std::vector <std::vector<int>> const &d) {
    for (auto const &v : d)
        os << v << "\n";
    return os;
}

int main(void) {
    std::vector<std::vector<int>> d(5, std::vector<int>(5, 42));

    std::cout << d;

    std::vector<std::thread> threads;

    for (int i = 0; i < 5; i++)
        threads.emplace_back([i, &d]() {std::fill(d[i].begin(), d[i].end(), i); });

    std::for_each(threads.begin(), threads.end(), [](std::thread &t){t.join(); });

    std::cout << "\n" << d;
}

答案 1 :(得分:2)

我解决了我的问题。一切都来自这条线:

threadList.at(i) = std::thread(&Toto::threadTask, toto, **vec**, i);

必须是:

threadList.at(i) = std::thread(&Toto::threadTask, toto, **&vec**, i);

我的函数'threadTask'必须在第一个参数中使用指针(而不是引用)。

void    threadTask(std::vector<int> *list, int value)
    {
        printf("b=%p\n", list);
        getchar();
        for (int x = 0; x < 5; x++) {
            (*list)[x] = value;
        }
    }

我希望这个例子可以帮助别人。