pthread_create函数: 线程创建
原函数:pthread_create(pthread *restrict tidp,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void *),
void *restrict arg)
参数:新线程ID,如果成功则新线程的ID回填充到tidp的内存
线程属性(调度策略,继承性,分高性)
回调函数(新线程要执行的函数)
回调函数的参数
返回值:成功返回0,失败则返回错误码
例:int err =pthread_create(&ntid,NULL,thread_fun,“new thread”);
编译时需要连接库libpthread
例:gcc -o main main.c -lpthread
注: linux中的pthread_t 并不是一个结构体,而是unsigned long int
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
void print_id(char *s)
{
pid_t pid;
pthread_t tid;
pid = getpid();
tid = pthread_self();
printf("%s pid is %u, tid is 0x%x\n",s,pid,(unsigned int)tid);
}
void *thread_fun(void *arg)
{
print_id(arg);
return (void *)0;
}
int main()
{
pthread_t ntid;
int err;
err = pthread_create(&ntid,NULL,thread_fun,"new thread");
if(err!=0)
{
printf("create new thread fail\n");
return 0;
}
print_id("main thread:");
sleep(2);
return 0;
}
运行结果
main thread: pid is 4857, tid is 0xfd6b9700
new thread pid is 4857, tid is 0xfcecb700
return、pthread_exit、exit
其中exit会导致进程退出
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
void *thread_fun(void *arg)
{
if(strcmp("1",(char *)arg)==0)
{
printf("new thread return!\n");
return (void *)1;
}
if(strcmp("2",(char *)arg)==0)
{
printf("new thread pthread_exit!\n");
pthread_exit((void *)2);
}
if(strcmp("2",(char *)arg)==0)
{
printf("new thread exit!\n");
exit(3);
}
}
int main(int argc, char *argv[])
{
int err;
pthread_t tid;
err = pthread_create(&tid,NULL,thread_fun,(void *)argv[1]);
if(err!=0)
{
printf("create new thread failed\n");
return 0;
}
sleep(1);
printf("main thread\n");
return 0;
}
运行结果
./pthread_exit 1
new thread return!
main thread
./pthread_exit 2
new thread pthread_exit!
main thread
./pthread_exit 3
main thread
pthread_join函数: 调用该函数的线程会一直阻塞,直到指定的线程id调用pthread_exit、从启动例程返回或者取消
原函数:int pthread_join(pthread_t tid,void ** rval)
参数:tid,指定线程的id
rval,指定线程的返回码,如果线程被取消,那么rval被置为PTHREAD_CANCELED
返回值:成功会返回0,失败返回错误码
例:err = pthread_join(tid1,(void*) &fp);
注: 调用pthread_join会使指定的线程处于分离的状态,如果指定线程已经处于分离状态,那么调用就会失败。
pthread_detach函数: 可以分离一个线程,线程可以自己分离自己
原函数:int pthread_detach(pthread_t thread);
参数:线程的id
返回值:成功返回0,失败返回错误码
例:pthread_detach(pthread_self());
pthread_self函数: 获得线程自身的ID
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
void *thread_fn1(void *arg)
{
printf("thread 1\n");
pthread_exit((void *)1);
}
void *thread_fn2(void *arg)
{
printf("thread 2\n");
pthread_detach(pthread_self());
pthread_exit((void *)2);
}
int main()
{
int err1,err2;
pthread_t tid1,tid2;
void *rval1,*rval2;
err1 = pthread_create(&tid1,NULL,thread_fn1,NULL);
err2 = pthread_create(&tid2,NULL,thread_fn2,NULL);
if(err1|| err2)
{
printf("creat thread failed\n");
}
printf("main thread\n");
printf("join1 rval is %d\n",pthread_join(tid1,&rval1));
printf("join2 rval is %d\n",pthread_join(tid2,&rval2));
printf("thread 1 exit code is %d\n",(int *)rval1);
printf("thread 2 exit code is %d\n",(int *)rval2);
}
运行结果
main thread
thread 2
thread 1
join1 rval is 0
join2 rval is 22
thread 1 exit code is 1
thread 2 exit code is 201205200
注: 线程2中调用了pthread_detach,无法连接,故返回错误码
pthread_cancel函数: 取消线程函数
原函数:int pthread_cancel(pthread_t tid)
参数:需要取消的线程的id
返回值:成功返回0,失败返回错误码
例:int cval=pthread_cancel(tid);
注: 取消tid指定的线程,所谓的取消只是发送一个请求,并不意味着等待线程终止,而且发送成功也不代表线程一定会终止。该函数需要被取消线程的配合,线程在很多时候会查看自己是否有取消请求,如果有就主动退出,这个查看是否有取消的地方称为取消点。
pthread_setcancelstate函数: 设置线程对取消信号的反应
原函数:int pthread_setcancelstate(int state,int *oldstate)
参数:state,PTHREAD_CAMCEL_ENABLE(响应取消信号)
PTHREAD_CANCEL_DISABLE(忽略取消信号)
oldstate,如果不为NULL则是存储原来的取消状态以便恢复
返回值:成功返回0 ,失败返回错误码
例:int stateval=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
注: 取消状态,就是线程对取消信号的处理方式,忽略或者响应。线程创建时默认的是响应取消信号。
pthread_setcanceltype函数: 设置线程取消动机的执行时机
原函数:int pthread_setcanceltype(int type, int *oldtype)
参数:type,PTHREAD_CANCEL_DEFERRED(收到取消信号后继续运行至下一个取消点再退出)
PTHREAD_CANCEL_ASYNCHRONOUS(收到取消信号后立即退出)。
注:这两个参数是在线程响应取消信号的时候才有作用(PTHREAD_CAMCEL_ENABLE)
oldtype,oldtype如果不设置为NULL则存储运来的取消动作类型值。
返回值:成功返回0,失败返回错误码
例:int typeval=pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
注: 取消类型,是线程对取消信号的响应方式,立即取消或者延时取消。线程创建时默认是延时取消。
取消点: 取消一个线程,它通常需要被取消线程的配合。
很多地方都是包含取消点,包括:pthread_join()、 pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait()、write、read,大多数会阻塞的系统调用
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
void *thread_fun(void *arg)
{
int stateval;
int typeval;
//设置不响应取消信号
stateval=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
if(stateval != 0)
{
printf("set cancel state failure\n");
}
printf("new thread\n");
//睡眠,返回执行主线程
sleep(4);
printf("about to cancel\n");
//设置为响应取消信号
stateval=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
if(stateval != 0)
{
printf("set cancel state failure\n");
}
//取消方式为延迟取消
typeval=pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
if(typeval != 0)
{
printf("set cancel type failure\n");
}
//因为设置的是延迟取消,所以在第一个取消点到来时就会取消,所以看不到第二句话的打印信息
printf("first cancel point\n");
printf("second cancel point\n");
return (void *)10;
}
int main()
{
pthread_t tid;
int err,cval,jval;
void *rval;
//创建新的线程
err=pthread_create(&tid,NULL,thread_fun,NULL);
if(err != 0)
{
printf("create thread failure\n");
return -1;
}
//睡眠,执行新的线程
sleep(2);
//发送取消信号
cval=pthread_cancel(tid);
if(cval != 0)
{
printf("cancel thread failure\n");
}
jval=pthread_join(tid,&rval);
printf("new thread exit code is %d\n",(int *)rval);
return 0;
}
运行结果
new thread
about to cancel
first cancel point
new thread exit code is -1