以下程序显示我们可以使用return()或pthread_exit()返回一个可用于pthread_join()状态变量的void *变量。
(1)是否应优先使用一个而不是另一个?
(2)为什么使用return()有效?通常我们会想到返回将值放在堆栈上但是由于线程已经完成,堆栈应该消失。或者直到pthread_join()之后堆栈才被销毁?
(3)在你的工作中,你是否看到很多地方变量的使用?我看到90%的代码看起来只是NULL状态参数。因为通过void * ptr改变的任何东西已经反映在调用线程中,所以返回它似乎没什么意义。返回的任何新的void * ptr都必须指向由开始线程进行malloc化的东西,这使得接收线程有责任处理它。我认为状态变量是无意义的,我错了吗?
#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
答案 0 :(得分:31)
(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 :(得分:6)
我认为来自return
的{{1}}更可取,因为它可以确保调用堆栈正确展开。
对于C而言,这比C ++更重要,因为它没有在初步退出后清理混乱的析构魔法。因此,您的代码应该遍历调用堆栈上的例程的所有最后部分,以执行start_routine
s等。
为什么这个有效,这很简单
如果start_routine返回,效果应该就像有一个 使用返回值隐式调用pthread_exit() start_routine作为退出状态
根据我的个人经验,我倾向于不使用终止线程的状态。这就是我经常开始线程free
的原因。但这在很大程度上取决于应用程序,当然不能推广。