首页 > 解决方案 > 类函数可以被线程调用并访问类数据吗?

问题描述

对于我必须为学校制作的一个项目,我被要求使用线程制作一个程序。我正在使用的库是<pthread.h>. 为了理解线程是如何工作的,我尝试在一个空白文件中编写一些代码来查看它们的行为方式。实际上,由于另一个stackoverflow问题,我发现了如何传递给pthread_create()类函数,并且它确实有效,但是现在又遇到了另一个问题,我在任何地方都找不到答案。该程序编译并打印与我放入类中的整数不对应的随机整数。也许线程调用的方法无法访问类内部的数据?那是代码:

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;
}

标签: c++multithreadingpthreads

解决方案


这里的主要问题是您试图将单个指针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(...)


推荐阅读