2

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

  1. 初始化具有唯一值“42”的 5x5 整数矩阵,包含在类“Toto”中(在主中初始化)。
  2. 我打印初始化的 5x5 矩阵。
  3. 声明std::vector5 个线程。
  4. 我将所有线程分别附加到它们的任务(threadTask方法)中。每个线程将操作一个std::vector<int>实例。
  5. 我加入所有线程。
  6. 我打印我的 5x5 矩阵的新状态。

这是输出:

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],输出是正确的。我认为我无法在主线程中打印正确的数据,因为 printData() 调用在主线程中,并且threadTask函数中的显示是正确的,因为该方法是在自己的线程中执行的(不是主线程)。奇怪,就是说在一个父进程中创建的所有线程都不能修改这个父进程中的数据?我想我忘记了代码中的某些内容。我真的迷路了。有人可以帮助我吗?非常感谢您的帮助。

4

2 回答 2

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;
}
于 2013-07-02T18:03:23.890 回答
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;
        }
    }

我希望这个例子对某人有所帮助。

于 2013-07-02T17:49:57.387 回答