大纲:
1.线程基础知识
2.线程编程
一.线程基础知识
1.线程和进程比较
和进程相比,是一种非常节俭的多任务操作方式。启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段,堆栈段
数据段。一个进程中的多个线程,他们之间使用相同的地址空间,线程间彼此切换时间远远小于进程
linux系统下,多线程遵循posix线程接口p.pthread,多线程包含头文件pthread.h和libpthread.a的库
多线程
二线程-编程
1.创建线程
int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,
(void*)(start_rtn)(void),void *arg);
tidp:线程id
attr:线程属性(通常为空)
stat_rtn:线程要执行的函数
arg:stat_rtn的参数
若线程创建成功,则返回0。若线程创建失败,则返回出错编号
2.线程的编译
pthread的库不是linux系统的库,所以编译的时候
gcc filename -lpthread
实例1:
#include
#include
#include
#include
#include
#include
#include
void *thread1(void){
int i;
for(i=0;i<50;i++){
printf("it is thread1\n");
sleep(1);
}
}
void *thread2(void){
for(i=0;i<50;i++){
int i;
printf("it is thread2\n");
sleep(2);
}
}
int main(){
int i=0,ret1=0,ret2=0;
pthread_t id1,id2;
ret1=pthread_create(&id1,NULL,(void *)thread1,NULL);
if(ret1){
printf("create error\n");
return -1;
}
ret2=pthread_create(&id1,NULL,(void *)thread2,NULL);
if(ret2){
printf("create error\n");
return -1;
}
pthread_join(id1,NULL);
pthread_join(id2,NULL);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
void *create(void *arg){
int *num;
num=(int*)arg;
printf("create is %d \n",*num);
return (void*) 0;
}
int main(int argc,char *argv[]){
pthread_t tidp;
int ret;
int test=4;
int *attr=&test;
ret=pthread_create(&tidp,NULL,create,(void*)attr);
if(ret!=0){
printf("create error\n");
return -1;
}
sleep(1);
printf("create success\n")
return 0;
}
3.线程的等待
int thread_join(pthread_t tid,void **rval_ptr);
功能:阻塞线程调用,直到指定线程终止
tid:等待退出的线程
rval_ptr:线程退出返回的指针
返回值 : 0代表成功。 失败,返回的则是错误号
#include
#include
#include
#include
#include
#include
#include
void *thread(void *str){
int i;
for(i=0;i<10;i++){
printf("this is the thread:%d\n",i);
return 0;//0表示程序正常执行,非0表示异常
}
}
int main(){
pthread_t pth;
int i;
int ret;
ret=thread_create(&pth,NULL,thread,(void*)(i));
pthread_join(pth,NULL);
printf(".....\n");
for(i=0;i<10;i++){
sleep(1);
printf("it is the main thread : %d\n",i);
}
return 0;
}
运行结果
注释掉pthread_join(pth,NULL);之后的执行结果
4.线程标识
pthread_t pthread_self(void)//获得当前线程id
5.线程清除
a.void Pthread_cleanup_push(void (rtn)(void),void *arg);//注册清理函数rtn,这个函数有一个参数arg。
rtn:清除函数
arg:清除函数的参数
什么时候进行调用Pthread_cleanup_push
1)调用pthread_exit。
2)作为对取消线程请求(pthread_cancel)的响应。
3)以非0参数调用pthread_cleanup_pop。
什么时候不可以调用Pthread_cleanup_push
1)如果线程只是由于简单的返回而终止的,则清除函数不会被调用。
2)如果pthread_cleanup_pop被传递0参数,则清除函数不会被调用,但是会清除处于栈顶的清理函数。
b.void Pthread_cleanup_pop(int execute)//清除函数弹出清除栈
execute:非0执行,0不执行。不管发生上诉那种情况,pop都将删除push调用建立的清理处理程序。
#include
#include
#include
#include
#include
#include
#include
#include
void *thr_fun1(void *arg){
print("thread 1 start");
pthread_cleanup_push((void*)clean,"thread 1 frist");
pthread_cleanup_push((void*)clean,"thread 1 second");
printf("thread 1 push complete\n");
if(arg){
return((void*));
}
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return((void*)1);
}
void *thr_fun2(void *arg){
print("thread 2 start");
pthread_cleanup_push((void*)clean,"thread 2 frist");
pthread_cleanup_push((void*)clean,"thread 2 second");
printf("thread 2 push complete\n");
if(arg){
pthread_exit((void*)2);
}
pthread_cleanup_pop(0);//取消第一个线程处理程序
pthread_cleanup_pop(0);
pthread_exit((void*)2);
}
int main(void){
int ret1,ret2;
pthread_t tid1,tid2;
void *tret;
ret1 = pthread_create(&tid1,NULL,thr_fun1,(void *)1);//创建线程
ret2 = pthread_create(&tid2,NULL,thr_fun2,(void *)2);
if(ret!=0){
printf("create error\n");
return -1;
}
pthread_join(tid1,&tret); //阻塞线程tid1
printf("thread 1 exit code\n");
pthread_join(tid2,&tret);
printf("thread 2 exit code/n");
exit(0);
}
1.push与pop一定是成对出现的,其实push中包含”{“而pop中包含”}”,少一个不行。
2.push可以有多个,同样的pop也要对应的数量,遵循”先进后出原则”。