【问题标题】:return() versus pthread_exit() in pthread start functionspthread 启动函数中的 return() 与 pthread_exit()
【发布时间】:2011-04-11 04:37:02
【问题描述】:

以下程序显示我们可以使用returnpthread_exit 来返回void* 变量,该变量可用于pthread_join 的状态变量。

  1. 是否应该优先使用一个而不是另一个?

  2. 为什么使用 return 有效?通常我们认为 return 将一个值放在堆栈上,但由于线程完成,堆栈应该消失。或者直到pthread_join之后堆栈才会被销毁?

  3. 在您的工作中,您是否看到状态变量的大量使用?我看到的 90% 的代码似乎只是将状态参数设置为 NULL。由于通过void* ptr 更改的任何内容都已反映在调用线程中,因此返回它似乎没有多大意义。返回的任何新的void* ptr 都必须指向启动线程的malloced,这使接收线程有责任处理它。我认为状态变量是半无意义的,我错了吗?

代码如下:

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

}

输出:

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

【问题讨论】:

    标签: c++ linux unix pthreads


    【解决方案1】:

    (1) 在 C++ 代码中,使用return 会导致堆栈展开并破坏局部变量,而pthread_exit 只能保证调用使用pthread_cancel_push() 注册的取消处理程序。在某些系统上,这种机制还会导致调用 C++ 局部变量的析构函数,但这不能保证可移植代码 --- 检查您的平台文档。

    另外,在main() 中,return 会隐式调用exit(),从而终止程序,而pthread_exit() 只会终止线程,程序会一直运行直到所有线程都终止或某个线程调用exit()abort() 或其他终止程序的函数。

    (2) return 的使用是有效的,因为 POSIX 规范是这样说的。返回的值存储在pthread_join() 可以检索的位置。在调用pthread_join() 之前,不会回收线程使用的资源。

    (3) 我从不在原始 POSIX 线程中使用线程的返回值。但是,我倾向于使用更高级别的工具,例如 Boost 线程库,以及最近的 C++0x 线程库,它们提供了在线程之间传输值的替代方法,例如期货,从而避免了与内存管理相关的问题。暗示。

    【讨论】:

    • 关于 (1),pthread_exit 不会立即终止线程,它首先运行取消处理程序。至少 NPTL/g++ 对取消处理程序和 C++ dtors 使用相同的机制,因此 pthread_exit 在这种情况下确实会展开堆栈。同样,OpenVMS pthread_exit/thread 取消展开堆栈并运行 C++ dtors。关于 pthread_exit 和堆栈展开的行为,您可能应该查看特定 pthread 实现的手册。
    • 我已经澄清 (1) 考虑您的评论。
    • 我肯定会买你的书 :)(希望它很快出来)。
    【解决方案2】:

    我认为start_routine 中的return 更可取,因为它确保调用堆栈正确展开。

    这对 C 来说比 C++ 更重要,因为它没有在初步退出后清理混乱的析构函数。因此,您的代码应该通过调用堆栈上例程的所有最后部分来执行frees 等操作。

    为什么会这样,这很简单

    如果 start_routine 返回,效果应该就像有一个 使用返回值隐式调用 pthread_exit() start_routine 作为退出状态

    就我个人的经验而言,我倾向于不经常使用已终止线程的状态。这就是为什么我经常让线程启动detached。但这应该在很大程度上取决于应用程序,而且肯定是不可推广的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-11
      • 1970-01-01
      • 2023-04-10
      • 2019-04-23
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      相关资源
      最近更新 更多