Linux 多线程编程

来源:
导读 大家好,我是本期栏目编辑小友,现在为大家讲解Linux 多线程编程问题。 最初,指向main()的线程被称为main thread使用pthread_create()

大家好,我是本期栏目编辑小友,现在为大家讲解Linux 多线程编程问题。

最初,指向main()的线程被称为main thread使用pthread_create()创建的线程,它被称为子线程。主/子线程只有在创建时才不同。它被创造出来后,会被平等对待。他们都是同样独立的个体。他们可以沟通,可以分享,可以私了,但是没有上下级,和多流程一样。只有在创建的那一刻,父进程和子进程才有区别。创作之后,他们都是一样的独立个体。创建子线程后,这两个线程独立运行。线程的执行顺序由操作系统的调度算法决定。线程是独立的,并且相互影响,因为当主线程结束时,进程也就结束了。会导致进程的所有线程都结束,多个线程共享一个进程,但是一个进程只有一个输出端,所以一定要调度好,不然看不到其他线程的输出。最低的方法是sleep(),以确保线程可以在创建线程之前完成执行model $ gcc-pthread # includepthhread . hpthread _ self()/pthread _ equal()//并在创建线程之前获取ThreadIDpthread _ attr _ init()/Set pthread _ create()/…//创建线程pthread _ detach()/pthread _ setcancelstate()/pthread _ setcanceltype()//在线程之后设置pthread _ kill()//发送信号pthread_exit() //退出线程而不执行比较两个线程id,pthread_equal()//如果相等则返回非0,如果不相等则返回0 int pthread _ equal (pthread _ tt1,pthread _ tt2);pthread _ attr _ init()/pthread _ attr _ destroy()//pthread _ attr _ init()初始化一个线程属性对象attr,并根据默认参数进行初始化,而不指定attr。//pthread_attr_destroy()销毁一个线程属性对象,被销毁的操作对使用此attr的线程有影响。//成功返回0,失败时返回错误号int pthread _ attr _ init(pthread _ attr _ t * attr)。int pthread _ attr _ destroy(pthread _ attr _ t * attr);更改attr对象的函数//成功返回0,错误号typedef struct { int detach state//线程int schedpolicy的分离状态;//线程调度策略结构sched _ param schedparam//线程的调度参数int inheritsched//线程的继承int作用域;//线程大小的范围_ t guardsize//线程堆栈int stackaddr _ set末尾的保护缓冲区大小;//线程的堆栈设置为void * stackaddr//线程堆栈大小_t stacksize的位置;//线程堆栈的大小} pthread _ attr _ t;PTHREAD _ attr _ setdetachstate(PTHREAD _ attr _ t * attr,int detachstate)PTHREAD _ attr _ getdetachstate(const PTHREAD _ attr _ t * attr,int * detachstate)PTHREAD _ CREATE _ JOINABLE/PTHREAD _ CREAT _ separantent detachstate;pthread _ attr _ getdetachstate(attr,detachstate);if(PTHREAD _ CREATE _ JINABLE==detachstate)printf(' 1。PTHREAD _ CREATE _ JINABLE \ n ');//defaultpthread_attr_setsched

policy(pthread_attr_t *attr, int policy);pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);SCHED_OTHER / SCHED_FIFO / SCHED_RRpthread_attr_setsschedchedparam(pthread_attr_t *attr, const struct sched_param *param);pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);struct sched_param { int sched_priority;// Scheduling priority,int sched_get_priority_max/sched_get_priority_min (int policy)};pthread_attr_seTInheritsched(pthread_attr_t *attr, int inheritsched);pthread_attr_geTInheritsched(const pthread_attr_t *attr, int *inheritsched);PTHREAD_INHERIT_SCHED / PTHREAD_EXPLICIT_SCHEDpthread_attr_setscope(pthread_attr_t *attr, int scope);pthread_attr_getscope(const pthread_attr_t *attr, int *scope);PTHREAD_SCOPE_SYSTEM / PTHREAD_SCOPE_PROCESSpthread_attr_setguardsize ( pthread_attr_t *attr, size_t guardsize );pthread_attr_getguardsize ( const pthread_attr_t *attr, size_t *guardsize );>0 / 0(默认1 page,当然还可以指定任意值)pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);pthread_attr_getstack(const pthread_attr_t *attr, void **stackaddr, size_t *stacksize);pthread_attr_setstacksize ( pthread_attr_t *attr, size_t size );pthread_attr_getstacksize ( const pthread_attr_t *attr, size_t *size );pthread_create()

//这个函数的create有‘e’ //p代表POSIX//在调用进程中创建一个新的线程,新的线程通过激活start_rouTIne()来开始执行,arg是start_rouTIne()唯一的参数//成功返回0,失败返回error numberint pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

thread:存放新线程的ID到该参数所指向的缓冲区中, pthread_t是unsigned long intattr: 线程的属性, 给NULL表示默认方式start_routine:指定新线程的处理函数,也就是新线程启动之后需要执行的代码,线程处理函数执行完毕之后, 新线程终止arg: 用于给start_routine传递实参(VS on_exit()) ,这个函数只支持传递void*型的型参,实际使用需要另外定义一个目标类型的指针,将arg强制类型转换后得到正确的类型

pthread_detach()

//将thread表示的线程标记为detached,当一个detached的线程结束后,它占用的资源被自动释放,其他线程也不能用pthread_join()等待//detach一个已经被detach了的线程将导致不确定的结果//成功返回0,失败返回error numberint pthread_detach(pthread_t thread);pthread_setcancelstate()

//设置当前线程是否允许被cancel,成功返回0,失败返回error number int pthread_setcancelstate(int state, int *oldstate);

state:设置新状态

PTHREAD_CANCEL_ENABLE //允许取消PTHREAD_CANCEL_DISABLE //不允许取消\

oldstate:用于带出设置之前的旧状态

pthread_setcanceltype()

//设置可取消性的类型,即当前线程何时被取消 //成功返回0,失败返回error number int pthread_setcanceltype(int type, int *oldtype);

type:设置新类型

PTHREAD_CANCEL_DEFERED //延迟取消PTHREAD_CANCEL_ASYNCHRONOUS //立即取消

oldtype:用于带出设置之前的旧类型

pthread_exit()

//结束调用线程并返回一个retval值,这个值可以被同进程中的其他线程通过pthread_join()来读取,当然,前提条件是当前线程可以被汇合/等待void pthread_exit(void *retval);线程的3种终止方式:简单的从启动例程中返回,返回值是线程的退出码线程可以被同一进程中的其他线程取消线程调用pthread_exit()pthread_cancel()

//发送一个结束请求给一个线程,是否取消以及何时取消取决于线程的属性:state和type//成功返回0,失败返回error numberint pthread_cancel(pthread_t thread);pthread_join()

//等待thread指定的线程终止,如果目标线程没有终止,则当前线程进入阻塞状态,当目标线程终止时,该函数立即返回,前提:目标线程可以被汇合/等待//如果调用pthread_join()的线程被cancel了,目标线程互保持joinable(不会被撤销)//如果多个线程同时join一个线程,那么结果是不确定的//成功返回0,失败返回error numberint pthread_join(pthread_t thread, void **retval);

thread:线程编号retval:二级指针的返回值retval

不是NULL,将拷贝目标线程的状态信息到*retval如果目标线程被cancel了,则将PTHREAD_CANCELED防止在*retval例子

//02join.c, 使用pthread_join等待目标线程结束#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<string.h> //strerror()//没有这个.h会把strerror(error)当intvoid* Calc(void* pv){ printf("primeter is %lg, area is:%lg\n",2*3.14**(int*)pv,3.14**(int*)pv**(int*)pv); return NULL; //要求有返回值,所以返回NULL}main(){ int* piRadius=(int*)malloc(sizeof(int)); printf("please input radius\n"); scanf("%d",piRadius); pthread_t thread; int error=pthread_create(&thread,NULL,Calc,(void*)piRadius); if(0!=error) printf("%s\n",strerror(error)),exit(-1); error=pthread_join(thread,NULL); if(0!=error) printf("%s\n",strerror(error)),exit(-1); free(piRadius); piRadius=NULL; return 0;}

//03join.c 使用pthread_join获取目标线程的退出状态#include<stdio.h>#include<stdlib.h>#include<string.h>#include<pthread.h>void* task(void* pv){ char* pc="hello"; return (void*)pc;}main(){ //创建子线程,使用pthread_create pthread_t thread; int error=pthread_create(&thread,NULL,task,NULL); if(0!=error) printf("%s",strerror(error)),exit(-1); //等待子线程结束,并获取退出状态信息 char* ps=NULL; error=pthread_join(thread,(void**)&ps); if(0!=error) printf("pthread_join %s\n",strerror(error)),exit(-1); printf("child thread returned:%s\n",ps); return 0;}

//使用pthread_create()创建新线程#include<stdio.h>#include<stdlib.h>#include<string.h>#include<pthread.h>void* task(void* pv){ //需要一个实参,我们又不需要,就可以给个NULL //判断thread中的线程ID是否与pthread_self()的线程ID相等 int res=pthread_equal(*(pthread_t*)pv,pthread_self()); if(0!=res) printf("these two are Equal\n"); else printf("these two are Unequal\n"); int i=0; for(i=0;i<10;i++){ printf("I am the new thread\n"); sleep(1); }}int main(){ //1.准备存储线程编号的变量 pthread_t thread; //2.创建新线程,使用pthread_create() int errno=pthread_create(&thread,NULL,task,(void*)&thread);//子线程执行完task()就结束了,使用arg把thread传入子线程 if(0!=errno) printf("pthread_create:%s\n",strerror(errno)),exit(-1); sleep(10); printf("child thread's ID:%lu,parent thread's ID:%lu\n",thread,pthread_self());//pthread_self(),获取当前线程自己的线程编号 return 0;}

//使用pthread_create()创建子线程,在线程处理函数中计算1~100之间的和,保存在sum中,返回该变量的地址,主线程等待子线程结束,并获取退出状态信息,并打印#include<stdio.h>#include<stdlib.h>#include<string.h>#include<pthread.h>void* Sum(void* pv){ int i=0,sum=0; for(i=1;i<=100;i++) sum+=i; printf("%d\n",sum); return (void*)"success"; //其实return "success"就行}int main(){ pthread_t thread; int res=pthread_create(&thread,NULL,Sum,NULL); if(0!=res) printf("%s",strerror(res)),exit(-1); char *retval=NULL; res=pthread_join(thread,(void**)&retval); if(0!=res) printf("%s\n",strerror(res)),exit(-1); printf("child thread return : %s\n",retval); return 0;}

//在线程处理函数中打印1~20之间的函数,当打印到10时终止当前进程并带出10,主线程等待并获取退出状态信息,打印最终结果#include<stdio.h>#include<pthread.h>void* task(void* pv){ static int i=0; for(i=1;i<=20;i++){ if(10==i) pthread_exit((void*)&i); //pthread_exit() VS exit() else printf("i=%d\n",i); } return NULL;}main(){ pthread_t thread; pthread_create(&thread,NULL,task,NULL); int *retval=NULL; pthread_join(thread,(void**)&retval); //没有错误处理 printf("task returned:%d\n",*retval); return 0;}

//使用pthread_cancel()取消指定的线程#include<stdio.h>#include<stdlib.h>#include<pthread.h>void* task(void* pv){ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); //设置该线程不可取消 while(1){ printf("I am superman\n"); sleep(1); } return NULL;}void* task2(void* pv){ printf("Cancelling thread...\n"); sleep(2); pthread_cancel(*(pthread_t*)pv); printf("cancelling successfully\n");}main(){ pthread_t thread; pthread_t thread2; pthread_create(&thread,NULL,task,NULL); pthread_create(&thread2,NULL,task2,(void*)&thread); pthread_join(thread,NULL); pthread_join(thread2,NULL); return 0;}/*I am supermanI am supermanCancelling thread...I am supermancancelling successfullyI am superman //取消失败了, 说明设置禁止取消成功了I am superman*/

标签:

版权声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢您的支持与理解。