参考:大丙老师线程
1.个数控制
2.创建线程
3.编译的时候需要注意:
4.线程退出
子线程是在主线程中创建的,因此主线程退出之后子线程也就结束运行,但是子线程的结束不影响主线程的的运行。
如下的示例,子线程并不会在终端打印出id信息,因为主线程运行结束之后就退出了并且释放了地址空间,因此子线程也无法运行了。
#include<pthread.h> #include<stdio.h> #include<stdlib.h> void* callback(void* arg); int main(){ pthread_t tid; pthread_create(&tid,NULL,callback,NULL); printf("main thread d:%ld\n",pthread_self()); } void* callback(void* arg){ printf("sun thread d:%ld\n",pthread_self()); return NULL; }
因此主线程的退出需要调用退出函数保证子线程还能正常运行,修改一下主线程(main函数)。
int main(){ pthread_t tid; pthread_create(&tid,NULL,callback,NULL); printf("main thread d:%ld\n",pthread_self()); pthread_exit(NULL); }
5.线程回收:主线程回收子线程的内核资源
代码如下:
#include<pthread.h> #include<stdio.h> #include<stdlib.h> struct ThInfo{ int num; int age; }; void* callback(void* arg); int main(){ pthread_t tid; pthread_create(&tid,NULL,callback,NULL); printf("main thread d:%ld\n",pthread_self()); void* arg; pthread_join(tid,&arg); struct ThInfo* info=(struct ThInfo*)arg; printf("sub thread age:%d,num:%d\n",info->age,info->num); } void* callback(void* arg){ struct ThInfo info; info.age=9; info.num=100; printf("sun thread d:%ld\n",pthread_self()); pthread_exit(&info); return NULL; }
运行结果如下:
子线程的回收参数不正确,是因为主线程退出时将栈的地址空间释放掉了,而子线程的临时变量也是放置在同一块空间中的,因此被释放掉之后就被其他值覆盖了。
解决方案:
(1)将callback中的结构体变量ThInfo indo设置为全局变量,这样就被放置在全局区,主线程中即可在全局区访问到正确的数值;
(2)callback中的结构体变量ThInfo indo在main函数中声明,相当于在栈中分配了一块空间用于接受保存子线程退出时的参数,将其地址传递给callback,callback将需要返回的结果写在这个空间中;
注意:指针与地址会有相应变化;
int main(){ pthread_t tid; struct ThInfo *info; pthread_create(&tid,NULL,callback,info); printf("main thread d:%ld\n",pthread_self()); void* arg; pthread_join(tid,&arg); info=(struct ThInfo*)arg; printf("sub thread age:%d,num:%d\n",info->age,info->num); } void* callback(void* arg){ struct ThInfo* info=(struct ThInfo*)arg; info->age=9; info->num=100; printf("sun thread d:%ld\n",pthread_self()); pthread_exit(info); return NULL; }
6.线程分离
子线程退出的时候,内核资源由其他进程接管回收,因此不需要主线程回收,也就不需要调用pthread_join()了,进而不会阻塞主进程。
int main(){ pthread_t tid; pthread_create(&tid,NULL,callback,NULL); pthread_detach(tid); pthread_exit(NULL); }
7.线程取消
第一步好理解,就是在A线程中调用pthread_cancel;
第二步的意思是,A中调用取消函数时并不会立刻结束B线程,而是要等到B中有系统调用的过程才会结束,比如调用printf系统调用,那么B就会结束。