简体   繁体   English

pthread启动函数中的return()与pthread_exit()

[英]return() versus pthread_exit() in pthread start functions

The following program shows that we can use return or pthread_exit to return a void* variable that is available to pthread_join 's status variable. 以下程序显示我们可以使用returnpthread_exit返回可用于pthread_join状态变量的void*变量。

  1. Should there be a preference for using one over the other? 是否应优先使用一个而不是另一个?

  2. Why does using return work? 为什么使用返回工作? Normally we think of return putting a value on the stack but since the thread is completed the stack should vanish. 通常我们会想到返回将值放在堆栈上但是由于线程已经完成,堆栈应该消失。 Or does the stack not get destroyed until after pthread_join ? 或者堆栈是否在pthread_join之后才被销毁?

  3. In your work, do you see much use of the status variable? 在您的工作中,您是否看到了很多状态变量的使用? It seems 90% of the code I see just NULLs out the status parameter. 我看到90%的代码看起来只是NULL状态参数。 Since anything changed via the void* ptr is already reflected in the calling thread there doesn't seem much point to returning it. 因为通过void* ptr改变的任何东西已经反映在调用线程中,所以返回它似乎没什么意义。 Any new void* ptr returned would have to point to something malloc ed by the start thread, which leaves the receiving thread with the responsibility to dispose of it. 返回的任何新的void* ptr都必须指向由启动线程进行malloc编辑的东西,这使接收线程有责任处理它。 Am I wrong in thinking the status variable is semi-pointless? 我认为状态变量是无意义的,我错了吗?

Here is the code: 这是代码:

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

using namespace std;

struct taskdata
{
       int  x;
     float  y;
    string  z;
};


void* task1(void *data)
{
    taskdata *t = (taskdata *) data;

    t->x += 25;
    t->y -= 4.5;
    t->z = "Goodbye";

    return(data);
}

void* task2(void *data)
{
    taskdata *t = (taskdata *) data;

    t->x -= 25;
    t->y += 4.5;
    t->z = "World";

    pthread_exit(data);
}


int main(int argc, char *argv[])
{
    pthread_t threadID;

    taskdata t = {10, 10.0, "Hello"};

    void *status;

    cout << "before " << t.x << " " << t.y << " " << t.z << endl;

    //by return()

    pthread_create(&threadID, NULL, task1, (void *) &t);

    pthread_join(threadID, &status);

    taskdata *ts = (taskdata *) status;

    cout << "after task1 " << ts->x << " " << ts->y << " " << ts->z << endl;

    //by pthread_exit()

    pthread_create(&threadID, NULL, task2, (void *) &t);

    pthread_join(threadID, &status);

    ts = (taskdata *) status;

    cout << "after task2 " << ts->x << " " << ts->y << " " << ts->z << endl;

}

With output of: 输出:

before 10 10 Hello
after task1 35 5.5 Goodbye
after task2 10 10 World

(1) In C++ code, using return causes the stack to be unwound and local variables destroyed, whereas pthread_exit is only guaranteed to invoke cancellation handlers registered with pthread_cancel_push() . (1)在C ++代码中,使用return会导致堆栈被展开并且局部变量被破坏,而pthread_exit只能保证调用使用pthread_cancel_push()注册的取消处理程序。 On some systems this mechanism will also cause the destructors for C++ local variables to be called, but this is not guaranteed for portable code --- check your platform documentation. 在某些系统上,这种机制也会导致调用C ++局部变量的析构函数,但这不能保证可移植代码 - 请查看您的平台文档。

Also, in main() , return will implicitly call exit() , and thus terminate the program, whereas pthread_exit() will merely terminate the thread, and the program will remain running until all threads have terminated or some thread calls exit() , abort() or another function that terminates the program. 另外,在main()return将隐式调用exit() ,从而终止程序,而pthread_exit()只会终止该线程,程序将保持运行,直到所有线程都终止或某些线程调用exit()abort()或终止程序的其他函数。

(2) The use of return works because the POSIX specification says so. (2) return的使用是有效的,因为POSIX规范是这样说的。 The returned value is stored in a place where pthread_join() can retrieve it. 返回的值存储在pthread_join()可以检索它的位置。 The resources used by the thread are not reclaimed until pthread_join() is called. 在调用pthread_join()之前,不会回收线程使用的资源。

(3) I never use the return value of a thread in raw POSIX threads. (3)我从不在原始POSIX线程中使用线程的返回值。 However, I tend to use higher level facilities such as the Boost thread library, and more recently the C++0x thread library, which provide alternative means for transferring values between threads such as futures, which avoid the problems associated with memory management that you allude to. 但是,我倾向于使用更高级别的工具,例如Boost线程库,以及最近的C ++ 0x线程库,它提供了在诸如期货之类的线程之间传输值的替代方法,从而避免了与内存管理相关的问题。暗示。

I think that return from the start_routine is preferable, because it ensures that the call stack is properly unwound. 我认为从start_routine return是更可取的,因为它确保调用堆栈被正确解开。

This is even more important for C than C++ since it doesn't have the destructor magic that cleans up the mess after preliminary exits. 这对于C而言比C ++更重要,因为它没有在初步退出后清理混乱的析构魔法。 So your code should go through all final parts of routines on the call stack to do free s and alike. 因此,您的代码应该遍历调用堆栈上的例程的所有最后部分,以执行free s等。

For why this works, this is simple 为什么这个有效,这很简单

If the start_routine returns, the effect shall be as if there was an implicit call to pthread_exit() using the return value of start_routine as the exit status 如果start_routine返回,则效果应该像使用start_routine的返回值作为退出状态对pthread_exit()进行隐式调用一样

For my personal experience I tend to not use the status of terminated threads much. 根据我的个人经验,我倾向于不使用终止线程的状态。 This is why I often have the threads started detached . 这就是我经常将线程detached But this should depend much on the application and is certainly not generalizable. 但这应该在很大程度上取决于应用程序,当然不能推广。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM