线程可以调用 Class 函数并访问 class 数据吗?
Can Class Function get called by Threads and get access to class data?
为了我必须为学校做的一个项目,我被要求用线程做一个程序。我使用的库是<pthread.h>
。为了了解线程是如何工作的,我尝试在一个空白文件中编写一些代码来查看它们的行为方式。由于另一个 Whosebug 问题,我实际上发现了如何将 pthread_create()
传递给 class 函数,并且它确实有效,但现在有另一个问题,我无法在任何地方找到答案。该程序编译并打印随机整数,这些整数与我放入 class 中的整数不一致。也许线程调用的方法无法访问 class 内的数据?那是代码:
class myClass {
public:
myClass() {
for(int i = 0; i < 5; i++)
values[i] = i*3;
}
void myFunction() {
pthread_t processIDs[5];
int count[5];
for(int i = 0; i < 5; i++) {
count[i] = i;
pthread_create(&processIDs[i], NULL, &printIntegerHelper, &count[i]);
}
for(int i = 0; i < 5; i++) {
pthread_join(processIDs[i], NULL);
}
}
private:
void* printInteger(int index) {
printf("%d", values[index]);
}
static void* printIntegerHelper(void* arg) {
Sleep(20);
return ((myClass *) arg)->printInteger(*((int*)arg));
}
protected:
int values[5];
};
int main(void){
myClass myObject;
myObject.myFunction();
return 0;
}
这里的主要问题是您试图将单个指针 arg
转换为指向不同的不相关事物的两个指针,然后取消对结果的引用。如果没有未定义的行为,您将无法做到这一点。你只能传递一个指向 pthread_create()
的指针,如果你需要传递更多的指针(例如,指针 + 索引),你需要一个额外的间接:将你的信息包装到一个 struct
(或 std::pair
/std::tuple
),然后传递一个指向它的指针。这就是 std::thread
内部所做的。
简单示例:
using Data = std::pair<myClass*, int>;
void myFunction() {
// ...
Data data[5];
for (int i = 0; i < 5; ++i) {
data[i] = {this, i};
pthread_create(&processIDs[i], NULL, &printIntegerHelper, &data[i]);
}
// ... (all created threads are joined here, so
// accessing data inside a thread is safe)
}
static void* printIntegerHelper(void* arg) {
const auto data = *reinterpret_cast<Data*>(arg);
data.first->printInteger(data.second);
return nullptr;
}
另请注意,非void
函数应该return
某些内容,即使该值以后不会使用。唯一的例外是 int main(...)
.
为了我必须为学校做的一个项目,我被要求用线程做一个程序。我使用的库是<pthread.h>
。为了了解线程是如何工作的,我尝试在一个空白文件中编写一些代码来查看它们的行为方式。由于另一个 Whosebug 问题,我实际上发现了如何将 pthread_create()
传递给 class 函数,并且它确实有效,但现在有另一个问题,我无法在任何地方找到答案。该程序编译并打印随机整数,这些整数与我放入 class 中的整数不一致。也许线程调用的方法无法访问 class 内的数据?那是代码:
class myClass {
public:
myClass() {
for(int i = 0; i < 5; i++)
values[i] = i*3;
}
void myFunction() {
pthread_t processIDs[5];
int count[5];
for(int i = 0; i < 5; i++) {
count[i] = i;
pthread_create(&processIDs[i], NULL, &printIntegerHelper, &count[i]);
}
for(int i = 0; i < 5; i++) {
pthread_join(processIDs[i], NULL);
}
}
private:
void* printInteger(int index) {
printf("%d", values[index]);
}
static void* printIntegerHelper(void* arg) {
Sleep(20);
return ((myClass *) arg)->printInteger(*((int*)arg));
}
protected:
int values[5];
};
int main(void){
myClass myObject;
myObject.myFunction();
return 0;
}
这里的主要问题是您试图将单个指针 arg
转换为指向不同的不相关事物的两个指针,然后取消对结果的引用。如果没有未定义的行为,您将无法做到这一点。你只能传递一个指向 pthread_create()
的指针,如果你需要传递更多的指针(例如,指针 + 索引),你需要一个额外的间接:将你的信息包装到一个 struct
(或 std::pair
/std::tuple
),然后传递一个指向它的指针。这就是 std::thread
内部所做的。
简单示例:
using Data = std::pair<myClass*, int>;
void myFunction() {
// ...
Data data[5];
for (int i = 0; i < 5; ++i) {
data[i] = {this, i};
pthread_create(&processIDs[i], NULL, &printIntegerHelper, &data[i]);
}
// ... (all created threads are joined here, so
// accessing data inside a thread is safe)
}
static void* printIntegerHelper(void* arg) {
const auto data = *reinterpret_cast<Data*>(arg);
data.first->printInteger(data.second);
return nullptr;
}
另请注意,非void
函数应该return
某些内容,即使该值以后不会使用。唯一的例外是 int main(...)
.