由于pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时,在编译中要加-lpthread参数:
[dmdba@localhost TEST]$ gcc MyThread.cpp -lpthread -o app
[dmdba@localhost TEST]$ ./app
位于同一虚拟地址空间中的线程,虽然不能共享栈区数据,但是可以共享全局数据区和堆区数据,因此在子线程退出的时候可以将传出数据存储到全局变量、静态变量或者堆内存中。
在子线程退出的时候可以使用pthread_exit()的参数将数据传出,在回收这个子线程的时候可以通过phread_join()的第二个参数来接收子线程传递出的数据。
// pthread_join.c
#include
#include
#include
#include
#include
// 定义结构
struct Persion
{
int id;
char name[36];
int age;
};
// 子线程的处理代码
void* working(void* arg)
{
printf("我是子线程, 线程ID: %ld\n", pthread_self());
for(int i=0; i<9; ++i)
{
printf("child == i: = %d\n", i);
if(i == 6)
{
struct Persion p;
p.age =12;
strcpy(p.name, "tom");
p.id = 100;
// 该函数的参数将这个地址传递给了主线程的pthread_join()
pthread_exit(&p);
}
}
return NULL; // 代码执行不到这个位置就退出了
}
int main()
{
// 1. 创建一个子线程
pthread_t tid;
pthread_create(&tid, NULL, working, NULL);
printf("子线程创建成功, 线程ID: %ld\n", tid);
// 2. 子线程不会执行下边的代码, 主线程执行
printf("我是主线程, 线程ID: %ld\n", pthread_self());
for(int i=0; i<3; ++i)
{
printf("i = %d\n", i);
}
// 阻塞等待子线程退出
void* ptr = NULL;
// ptr是一个传出参数, 在函数内部让这个指针指向一块有效内存
// 这个内存地址就是pthread_exit() 参数指向的内存
pthread_join(tid, &ptr);
// 打印信息
struct Persion* pp = (struct Persion*)ptr;
printf("子线程返回数据: name: %s, age: %d, id: %d\n", pp->name, pp->age, pp->id);
printf("子线程资源被成功回收...\n");
return 0;
}
作者: 苏丙榅
链接: https://subingwen.cn/linux/thread/?highlight=%E7%BA%BF%E7%A8%8B
来源: 爱编程的大丙
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果多个线程共用同一个虚拟地址空间,每个线程在栈区都有一块属于自己的内存,相当于栈区被这几个线程平分了,当线程退出,线程在栈区的内存也就被回收了,因此随着子线程的退出,写入到栈区的数据也就被释放了。
struct Persion p; // 定义全局变量
// 子线程的处理代码
void* working(void* arg)
{
printf("我是子线程, 线程ID: %ld\n", pthread_self());
for(int i=0; i<9; ++i)
{
printf("child == i: = %d\n", i);
if(i == 6)
{
// 使用全局变量
p.age =12;
strcpy(p.name, "tom");
p.id = 100;
// 该函数的参数将这个地址传递给了主线程的pthread_join()
pthread_exit(&p);
}
}
return NULL;
}
struct Persion p;
// 主线程的栈内存传递给子线程
pthread_create(&tid, NULL, working, &p);
如果让主线程负责子线程的资源回收,调用pthread_join()只要子线程不退出主线程就会一直被阻塞,主要线程的任务也就不能被执行了。
pthread_detach(tid);
pthread_exit(NULL);