【问题标题】:Can Class Function get called by Threads and get access to class data?类函数可以被线程调用并访问类数据吗?
【发布时间】:2020-11-03 07:28:25
【问题描述】:

对于我必须为学校制作的项目,我被要求使用线程制作程序。我使用的库是<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;
}

【问题讨论】:

  • (myClass*)arg, (int*)arg - 通过将相同 arg 转换为两种不同的类型,您期望什么?
  • 你只能传递一个指针。如果您想传递更多信息,请将其包装成 struct 并传递一个指向它的指针。
  • 我在哪里传递的不仅仅是一个指针?我只是传递一个索引
  • 您还有其他一些问题。 void* myFunction(void) 不返回值,但您已声明它应该返回 void* - 因此您的程序具有未定义的行为。改为void myFunction()(跳过参数列表中的void - 它对C++没有影响)。
  • 您使用pthread_create() 调用的函数确实必须声明为返回void* - 但不是其他不返回任何内容的函数。

标签: c++ multithreading pthreads


【解决方案1】:

这里的主要问题是您试图将单个指针 arg 转换为指向不同不相关事物的两个指针,然后取消引用结果。如果没有未定义的行为,您将无法做到这一点。您只能将一个指针传递给pthread_create(),如果您需要传递更多(例如,指针+索引),则需要额外的间接:将您的信息包装到struct(或std::pair/@987654325 @),然后传递一个指向它的指针。这就是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(...)

【讨论】:

  • 谢谢!我解决了我的问题。
  • @Evg 公平点。我完全忽略了在同一个函数中加入线程,因为它非常罕见:-) 删除 cmets 并给你我的投票 :-)
猜你喜欢
  • 2016-03-08
  • 1970-01-01
  • 2019-12-14
  • 2022-11-12
  • 2015-02-20
  • 1970-01-01
  • 2012-10-28
  • 1970-01-01
  • 2018-12-08
相关资源
最近更新 更多