我編寫了一個小型C++程序,試圖瞭解多線程如何使用std::thread
工作。這裏是我的程序執行的步驟:多線程無法正常使用std :: thread(C++ 11)
- 初始化一個5×5整數矩陣,其中包含'Toto'類(初始化爲主)中包含的唯一值'42'。
- 我打印初始化的5x5矩陣。
- 聲明:
std::vector
共5線程。 - 我附加所有線程分別與他們的任務(
threadTask
方法)。每個線程將操縱一個std::vector<int>
實例。 - 我加入所有主題。
- 我打印了我的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]
,輸出是c orrect。我認爲我無法在main中打印正確的數據,因爲printData()調用位於主線程中,並且threadTask
函數中的顯示是正確的,因爲該方法在其自己的線程(不是主線程)中執行。奇怪的是,這意味着在父進程中創建的所有線程都不能修改此父進程中的數據?我想我在代碼中忘記了一些東西。我真的迷失了。有人可以幫我嗎? 提前感謝您的幫助。
您需要了解C++值和引用語義。 'std :: vector vec = toto.getData()[i];'製作矢量的一個副本,所以原始文件永遠不會被改變。該副本也會被複制到線程對象中,並且再也不會影響原始對象。 –
我使用getDataByRange新函數更新了我的問題,該函數根據範圍返回對特定子向量的引用。所以我不會返回一個副本,而是一個參考。輸出與修改後的輸出相同。 – user1364743
問題不在於getData函數,它是與std :: vector vec = ...部分。這將調用vecs拷貝構造函數,vec將是getData返回的不同對象。 作爲一個方面說明。考慮使用矢量構造函數在類構造函數中初始化矢量。 Toto():m_data(5,std :: vector (5,42)){ } 在我看來是一個更清潔的實現。 –