pthread基本操作
- 进程的创建(pthread_create)
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg)
RETURN VALUE
On success, pthread_create() returns 0; on error, it returns an error number.
函数参数:
1. pthread_t *thread, 传入创建的pthread_t指针。
2.const pthread_attr_t *attr,修改进程的属性,如果不设置则可以传入NULL
3.void *(*start_routine) (void *)创建出来的进程执行的函数,返回类型为void*,并且需要带参数void*
4. void *arg 传入的函数参数。
在给函数传参数的时候,如果只是单纯的传入数字,我们可以采用(大致的写几行伪代码):
void* fun(void *arg){ int i = (argumentType)arg; } main(){ int i; pthread_t pid; pthread_create(&pid,NULL,fun,(void*)i);}
如果是在32位操作系统,此代码中的argumentType应该写为int,因为void*指针的大小也是4位。
如果是在64位操作系统,此代码中的argumentType应该写为long,因为void*指针的大小是8位,如果使用int会报错而不通过编译。
这里采用int转void*,而不是int* 转 void*的原因是,如果实在多线程的创建过程中,传递的是地址,其他线程如果修改这个数据,在本线程的后续操作中会使数据改变而导致达不到自己想要的效果。
当我们需要传递多个参数的时候,便可以采用结构体,定义一个结构体数据,然后通过指针传递给函数,接着转换一下类型就好了。
- pthread_join, pthread_detach
typedef struct retval{ int id; char str[10]; }*pretval; void *fun1(void *arg){ pretval argtemp = (pretval)arg; argtemp->id = 123123; printf("%d,%s\n",argtemp->id,argtemp->str); pthread_exit(argtemp); } int main() { pthread_t pthread1; retval* arg = new retval; arg->id = 10; strcpy(arg->str,"hello123"); int rect = pthread_create(&pthread1,NULL,fun1,(void*)arg); pthread_join(pthread1,(void **)&arg); printf("this is main %d %s\n",arg->id,arg->str); }
pthread_join用来回收线程,需要指定回收线程的ID和线程的返回参数(可选),这个例子是使用结构提体参,在线程函数中改变结构体变量的值,然后传递给pthread_join,接着显示修改后的值。这样基本上就了解了pthread_join的用法,另外pthread_join是阻塞函数。
如果不回收死亡的线程,便会产生僵尸线程。
pthread_detach使用来分离线程,如果我们使用了pthread_detach,那么这个进程在执行完自己的任务之后便会自动死亡并回收。
但是如果使用了detach之后,再使用join,join的返回值将会是错误的number,好像是22。
如果我们使用很多的线程,使用pthread_detach是有一点不太方便,这个时候我们便可以使用上面pthread_create函数的第二个参数来设置创建进程的属性。
#include <pthread.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> void *fun(void *){ printf("hello\n"); //pthread_cond_timedwait(); exit(1); return NULL; } int main() { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); pthread_t pid; pthread_create(&pid,&attr,fun,NULL); sleep(20); return 0; }
需要注意的是需要初始化之后赋值才能使用,不然有可能会达不到你的期望。
- pthread_cancel
pthread_cancel,是计算机语言,它发送终止信号给thread线程,如果成功则返回0,否则为非0值。
- 有关线程的退出问题
接下来我们聊聊exit,_exit,return,pthread_exit.
_exit():会结束整个进程,不论缓冲区是否有数据。
exit():会结束整个进程,缓冲区有数据就写到指定的文件描述符。
return:只是单纯的返回到函数到用的地方,但是当main函数使用的时候,就会退出整个进程,所以要使用pthread_exit.如果是其他线程,则只会退出自己。
pthread_exit:只会退出单个线程,不影响其他线程。