4

阅读此线程后:How to return a value from thread in C on how to return an integer value from a pthread 我测试了它是否可以用于双精度,但它没有。有没有办法像原始线程中描述的那样从 pthread 进程返回双精度、长整数或字符串,而不是返回整数 42?

如果是怎么办?

如果我有一个包含 10 个位置的静态数组和 10 个 pthreads 每次修改不同的位置,我会遇到麻烦吗?一个例子就像“线程 0 只修改数组 [0],线程 1 只修改数组 [1] 等等”。

4

3 回答 3

4

线程只需为您希望它返回的结果动态分配内存:

void *myThread(void*)
{
   double* result = (double*) malloc(sizeof(double));

   *result = 42.0;

   return result;
}

应该收集该结果的任何内容都会取消引用使用适当强制转换返回的指针(void*毕竟这是 C),然后释放内存:

// calling thread (or whatever will collect the value)
void* thread_result;
int err = pthread_join( thread_handle, &thread_result);

double dbl = *(double*) thread_result;
free(thread_result);

作为替代方案,无论创建什么线程,都可以将指针传递给线程应该将它的结果放入线程的void*参数中(如果线程需要的不仅仅是那一点信息,则可能作为结构的一部分)。如果您有理由避免动态内存分配,这可能会让您避免动态内存分配,但它可能会使数据的所有权和生命周期管理起来更加复杂。

于 2013-03-12T05:26:52.213 回答
2

这些只是将Steve Jessop 的 C 解决方案重新表述为 C++。这些玩具示例(注意缺少错误检查)使用模板来明确如何更改代码以使用double. 例如,如果在工作完成后需要返回多个值,则double可以将 替换为类型。class在实践中,基类和模板可能会被删除,并且work()方法MyWorker将由调用者直接调用,而不是通过虚拟方法。

首先,使用pthread

#include <iostream>
#include <pthread.h>

class WorkerBase {
protected: virtual ~WorkerBase () {}
public:    virtual void * work () = 0;
};

template <typename T>
struct Worker : public WorkerBase { T result; };

extern "C" void *invoke_worker (void *arg) {
    return static_cast<WorkerBase *>(arg)->work();
}

struct MyWorker : public Worker<double> {
    void * work () {
        result = 4.2;
        return 0;
    }
};

int main () {
    pthread_t t;
    MyWorker w;
    pthread_create(&t, 0, invoke_worker, &w);
    pthread_join(t, 0);
    std::cout << "result: " << w.result << std::endl;
    return 0;
}

其次,使用 C++11 std::thread

#include <iostream>
#include <thread>

class WorkerBase {
protected: virtual ~WorkerBase () {}
public:    virtual void work () = 0;
           static void invoke (WorkerBase *w) { w->work(); }
};

template <typename T>
struct Worker : public WorkerBase { T result; };

class MyWorker : public Worker<double> {
    void work () { result = 4.2; }
};

int main () {
    MyWorker w;
    std::thread t(MyWorker::invoke, &w);
    t.join();
    std::cout << "result: " << w.result << std::endl;
    return 0;
}

你的帖子中有另一个我错过的问题:

如果我有一个包含 10 个位置的静态数组和 10 个 pthreads 每次修改不同的位置,我会遇到麻烦吗?

这是否会给您带来麻烦可能取决于数组元素类型和您的硬件架构。在实践中,对于在机器字边界上对齐的数组元素,我没有观察到这在 x86 架构上是一个问题。

于 2013-03-12T03:31:37.797 回答
1

我不认为这太难了。我不使用 cstdlib 中的 malloc(size_t),而只是新的。下面的示例将参数作为结构传递给线程,并返回另一个结构。为了表明它可以采用任何变量类型,我还使用了字符串向量...

#include <iostream>
#include <pthread.h>
#include <vector>
#include <string.h>
#include <cstdlib>
using namespace std;

struct thread_data {
    int number;
    vector<string> strings;
    thread_data (){}
    thread_data(int nr) {
        number = nr;
        strings.push_back("aba\n");
    }
};

struct thread_return_data {
    int S;
    vector<string> R;
};

void *Thread (void *threadarg) {
    thread_return_data *R = new thread_return_data;
    thread_data * Q;
    Q = (thread_data *) threadarg;
    cout << Q->number << endl;
    R->S = 16; //random number
    R->R.push_back("14fjnv"); //random string
    R->R.push_back("28jfhn"); //random string
    pthread_exit(R);
    return 0;
}

int main() {
    thread_data A(4444); //initialize with random int
    thread_return_data *B; //is pointer
    pthread_t aThread; //is variable

    pthread_create(&aThread, NULL, Thread, (void *)&A);
    pthread_join(aThread, (void **)&B);

    cout << B->S << endl;
    cout << B->R[0] << endl;
    cout << B->R[1] << endl;
    cout << A.strings[0];
    delete B;

    return 0;
}    
于 2013-05-09T13:48:38.970 回答