c++ - 如何从 C++ 中的父线程或子线程将值传递给子线程下的孙线程
问题描述
我有一个具有以下值的 file.txt:1234 567 8910
我想在 C++ 中创建一个程序,它创建 x 个子线程,其中 x 是“file.txt”中的行数。子线程接收该行,因此它将该行拆分为数字并将它们存储在一个数组中。
然后我想在每个子线程下创建 y 个孙线程,其中 y 是该子线程数组或接收到的行值中的位数,并将每个孙线程传递一个数字。
比如上面的file.txt,我在main()中的父线程会创建3个子线程。第一个子线程将收到“1234”,第二个“567”,第三个“8910”。然后第一个孩子将创建 4 个孙线程并传递第一个孙线程“1”,第二个“2”,第三个“3”,第四个“4”。同样,第二个子线程将创建 3 个孙线程并传递“5”、“6”、“7”位。最后,第三个孩子将创建 4 个孙线程并传递“8”、“9”、“1”、“0”数字。
我想使用多线程并行传递所有这些值。在子线程之前,我能够让一切正常工作,并且我能够创建适量的孙线程,但我无法将值传递给它们。非常感谢任何帮助和指导。
这是我的代码:(请指导我修复它)
#include <iostream>
#include <pthread.h>
#include <math.h>
#include <fstream>
#include <sys/wait.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
struct info {
int* digit = new int;
int* totalDigits = new int;
};
struct grandchildThreadData {
int GCTDdigit;
int GCTDgrandchildIndex;
int GCTDchildIndex;
info* GCTDinfo = new info;
info* GCTDparentInfo = new info;
};
struct childThreadData {
long int CTDlineValue;
int CTDchildIndex;
info* CTDinfo = new info;
};
// thread declaration
void* childThread(void*);
void* grandchildThread(void*);
// function to convert and store line to digits
int* digitSeparator(long int);
// MAIN PROGRAM
int main() {
// FILE OPENING
int totalLines{0};
ifstream file1("file.txt"), file2("file.txt");
string temp;
while (getline(file1, temp)) {
totalLines++;
}
file1.close();
long int* valueOnLine = new long int[totalLines];
int i =0;
while (!file2.eof()) {
file2 >> valueOnLine[i];
i++;
}
file2.close();
// FILE CLOSING
// THREAD START
static struct info* mainInfo = new info[totalLines];
pthread_t* child = new pthread_t[totalLines];
// will be used to pass values to child
static struct childThreadData* Carg = new childThreadData[totalLines];
// Creating Childthreads
for (int i = 0; i < totalLines; i++) {
Carg[i].CTDinfo[i] = mainInfo[i];
Carg[i].CTDchildIndex = i;
Carg[i].CTDlineValue = valueOnLine[i];
if (pthread_create(&child[i], nullptr, childThread, &Carg[i])) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
}
// Joining Childthreads
for (int i = 0; i < totalLines; i++) {
if (pthread_join(child[i], nullptr)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
}
delete[] valueOnLine;
delete[] child;
delete[] Carg;
return 0;
}
void* childThread(void* i) {
struct childThreadData* CTptr = (struct childThreadData*)i;
int totalDigits = log10((float)CTptr->CTDlineValue) + 1;
int* numberArray = digitSeparator(CTptr->CTDlineValue);
// THIS LINE WILL PUT TOTAL DIGITS INTO mainInfo
CTptr->CTDinfo[CTptr->CTDchildIndex].totalDigits[0] = totalDigits;
static struct info* childInfo = new info[totalDigits]; // This can be used to print modified info in grandchild
pthread_t* grandchild = new pthread_t[totalDigits];
static struct grandchildThreadData* GCarg = new grandchildThreadData[totalDigits];
// THIS LINE WILL PUT EACH DIGIT ON CORRECT LOCATION of mainInfo
for (int i=0; i< totalDigits; i++) {
CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i] = numberArray[i];
}
// GRANDCHILD THREAD
for (int i = 0; i < totalDigits; i++) {
GCarg[i].GCTDinfo[i] = childInfo[i]; // grandchild to child communication but does not work
// or
GCarg[i].GCTDparentInfo[i] = CTptr->CTDinfo[i]; // grandchild to parent communication but does not work
GCarg[i].GCTDgrandchildIndex = CTptr->CTDchildIndex; // Here CTptr->CTDchildIndex should pass 0, 1, 2 to grandchild but I get different values
GCarg[i].GCTDchildIndex = i; // This line works fine for some reason
GCarg[i].GCTDdigit = CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i]; // This line should pass the correct digit, but again, I am getting different results in grandchild
if (pthread_create(&grandchild[i], nullptr, grandchildThread, &GCarg[i])) {
fprintf(stderr, "Error creating thread\n");
}
}
//Joining GrandChildthreads
for (int i = 0; i < totalDigits; i++) {
if (pthread_join(grandchild[i], nullptr)) {
fprintf(stderr, "Error joining thread\n");
}
}
return nullptr;
}
void* grandchildThread(void* i) {
struct grandchildThreadData* GCTptr = (struct grandchildThreadData*)i;
// THIS LINE SHOULD PRINT THE DIGIT
cout << GCTptr->GCTDdigit;
return nullptr;
}
int* digitSeparator(long int number) {
int totalDigits = log10((float)number) + 1;
int* separatorPtr = new int[totalDigits];
int j = 0;
for (int i = totalDigits - 1; i >= 0; i--) {
long int divisor = pow((float)10, i);
long int digit = number / divisor;
number -= digit * divisor;
separatorPtr[j] = digit;
j++;
}
return separatorPtr;
}
解决方案
这不是程序中问题的详尽列表,但它处理了一些基本问题。
您的程序不会检查是否
file.txt
已成功打开。如果不是,程序将继续运行,直到出现有符号整数溢出——这意味着程序具有未定义的行为。如果文件成功打开,你会遇到 heap-buffer-overflow
// Creating Childthreads for(int i = 0; i < totalLines; i++) { Carg[i].CTDinfo[i] = mainInfo[i]; // <- here
那是因为
CTDinfo[i]
当 时越界i > 0
。CTDinfo
是一个指向一个单info
- 不是stotalLines
的指针。info
下面也一样。
CTDinfo
不能将其视为数组,因为它是指向单曲的指针info
- 并且digit
是指向单曲的指针int
- 而不是int
.// THIS LINE WILL PUT EACH DIGIT ON CORRECT LOCATION of mainInfo for(int i = 0; i < totalDigits; i++) { CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i] = numberArray[i]; }
建议:
- 编写一个小得多的程序来掌握线程的窍门。
- 编写一个小得多的程序来学习如何构建非常复杂的结构(如果你真的需要这样做的话)。使用 C++ 类,例如
std::vector
. 如果您用标准 C++ 容器替换所有手动内存管理,我怀疑这个程序是否需要单个new
/ 。new[]
好像info
有什么误会似的。没有理由在这里使用指针:struct info { int* digit = new int; int* totalDigits = new int; };
- 使用
std::thread
及其支持的函数和类代替pthread
.
推荐阅读
- laravel - 如何将 laravel 默认 cookie 加密更改为 SHA-256 或 SHA-512?
- c# - Blazor WASM CheckSession 循环
- python - 如何强制 keras 使用 tensorflow GPU 后端
- python - 循环功能无法正确水平附加数据帧
- pandas - 相同的 x 值会混淆 Matplotlib,因此 y 值与不正确的 x 值相关联
- python - 根据可能的配对创建组合
- java - 我想要 JSON 对象的键和值
- swift - 在 Objective-C 中访问嵌套的 Swift 枚举
- vue.js - 使用 rest api 使用 vue js(Nuxt SSR) 创建一个管理面板。它安全吗?
- ios - 如何并行使用 Swift async/await