在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一、多线程 VS 多进程 和进程相比,线程有很多优势。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护代码段和数据。而运行于一个进程中的多个线程,他们之间使用相同的地址空间。正是这样,同一进程下的线程之间共享数据空间,数据可以相互使用,并且线程间切换也要更快些,可以更有效的利用CPU。 二、程序设计 [注] 头文件<pthread.h> 编译时要加载动态库 libpthread.a,使用 -lpthread 复制代码 代码如下:int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void), void *arg) tidp为线程id,是函数分配的值,所以要传一个 pthread_t 的地址。 attr线程属性,通常为空。 start_rtn为线程要执行的函数,返回值为空指针,参数为后面的*arg 若成功则返回0,否则返回出错编号。 例: 复制代码 代码如下:#include<stdio.h> #include<pthread.h></p> <p>void *func1(void *arg){ //原函数声明 int i; for(i=0;i<5;i++){ printf("this is func1! The num is %d\n",*(int*)arg); //将空指针转换为int型指针 sleep(1); } }</p> <p>void *func2(int *m){ //自定义类型声明,也可以定义非指针类型,但是在create时会有警告,因为非地址并不能改变传入的值 int i; for(i=0;i<5;i++){ printf("this is func2! The num is %d\n",*m); (*m)++; sleep(1); } }</p> <p>int main(){ pthread_t id1,id2; int num = 5; int *p = # if(pthread_create(&id1,NULL,(void *)func1,(void *)p) != 0){ printf("thread1 create error!\n"); return -1; } if(pthread_create(&id2,NULL,(void *)func2,&num) != 0){ printf("thread2 create error!\n"); return -1; } pthread_join(id1,NULL); //等待线程结束 pthread_join(id2,NULL); printf("Running complete!\n"); return 0;</p> <p> } 运行结果: 复制代码 代码如下:[fsy@localhost process]$ gcc thC.c -o thC -lpthread -g [fsy@localhost process]$ ./thC this is func2! The num is 5 this is func1! The num is 6 this is func2! The num is 6 this is func1! The num is 7 this is func2! The num is 7 this is func1! The num is 8 this is func2! The num is 8 this is func1! The num is 9 this is func2! The num is 9 this is func1! The num is 10 Running complete! [fsy@localhost process]$
[注]当调用pthread_create函数时,线程并没有开始执行,主进程应有等待,比如用sleep,或者用更专业的函数:pthread_join 复制代码 代码如下:int pthread_join(pthread_t tid, void **rval_ptr) 调用函数可以阻塞调用线程,直到指定的线程终止。 tid为等待退出线程的id,rval_ptr为函数的返回值。是指向指针的指针,可以置空。 例: 复制代码 代码如下:#include<stdio.h> #include<pthread.h> #include<stdlib.h></p> <p>void *func(int *p){ int *num=(int *)malloc(sizeof(int)); //必须动态创建,原因可以参考我动态分配内存的博客 printf("Please input the number: "); scanf("%d",num); return (void *)num; //类型是pthread_create的参数规定的 }</p> <p>int main(){ pthread_t pth; void *a; if(pthread_create(&pth,NULL,(void *)func,NULL) != 0){ printf("create thread error!\n"); return 1; } pthread_join(pth,&a); //指向空指针的指针 printf("get the num from the thread, it's %d\n",*(int *)a); return 0; } 3、终止线程 线程终止有以下三种方式: 1、线程从函数中返回 复制代码 代码如下:void pthread_exit(void *rval_ptr) rval_ptr为线程退出返回值的指针,即函数返回值。 4、退出清除 复制代码 代码如下:void pthread_cleanup_push(void (*rtn)(void*), void *arg) rtn为清除函数,arg是清除函数的参数 复制代码 代码如下:void pthread_cleanup_pop(int execute) 当execute 非0时执行清除函数。为0时不执行。 从pthread_cleanup_push的调用点到pthread_cleanup_pop之间的程序段中,如果有终止进程的动作,如调用pthread_exit或异常终止(不包括return),就会执行pthread_cleanup_push()所指定的清理函数。多个嵌套匹配时,就近匹配。 复制代码 代码如下:#include<stdio.h> #include<pthread.h></p> <p>void *clean(char *argv){ printf("clean is called by %s\n",argv); return NULL; } void *func1(void *argv){ printf("welcome enter the func1!\n"); pthread_cleanup_push((void*)clean,"the first time call!"); pthread_cleanup_push((void*)clean,"the second time call!"); if(argv){ return (void *)1; //第二次运行将此句注掉 } pthread_cleanup_pop(0); pthread_cleanup_pop(1); return (void *)0; }</p> <p>void *func2(void *argv){ sleep(1); //两个线程运行先后不确定 printf("welcome enter the func2!\n"); pthread_cleanup_push((void*)clean,"the first time call!"); pthread_cleanup_push((void*)clean,"the second time call!"); if(argv){ pthread_exit(NULL); } pthread_cleanup_pop(0); pthread_cleanup_pop(0); return (void *)0; }</p> <p> int main(){ pthread_t tid1,tid2; if(pthread_create(&tid1,NULL,(void *)func1,(void *)1) != 0){ printf("thread1 create error!\n"); return 1; }</p> <p> if(pthread_create(&tid2,NULL,(void *)func2,(void *)1) != 0){ printf("thread2 create error!\n"); return 1; } pthread_join(tid1,NULL); pthread_join(tid2,NULL); return 0; } 运行结果: 复制代码 代码如下:[fsy@localhost process]$ gcc thClean.c -o thclean -lpthread [fsy@localhost process]$ ./thclean welcome enter the func1! welcome enter the func2! clean is called by the second time call! //此处先2后1 clean is called by the first time call! [fsy@localhost process]$ vim thClean.c [fsy@localhost process]$ gcc thClean.c -o thclean -lpthread [fsy@localhost process]$ ./thclean welcome enter the func1! clean is called by the first time call! //second已经被pop welcome enter the func2! clean is called by the second time call! clean is called by the first time call! [fsy@localhost process]$ |
请发表评论