线程 属性取消线程多线程
Posted hello-liuliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程 属性取消线程多线程相关的知识,希望对你有一定的参考价值。
12.6 线程的属性:
线程创建后,在程序退出之前我们可以通过pthread_join再次与线程同步,在结束的时候向主线程返回一些数据。有时候我们不需要线程结束的时候向主线程返回数据,也不需要主线程等待他的结束,这一类型的线程叫做脱离线程。可以通过修改线程的属性或者pthread_deatch的方法来创建它们。
线程属性最重要的函数就是pthread_attr_init,它的作用是初始化一个线程属性对象。
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
与前面一样,该函数成功时返回0,失败时返回错误代码。
还有一个回收函数pthread_attr_destory,它的目的是对属性对象进行清理和回收,一旦对象回收 了,除非重新被初始化,否者不能再使用。
初始化一个线程对象后,我们就可以调用其他的函数来设置不同的属性行为。主要的函数如下:
1 #include<pthread.h> 2 int pthread_attr_setdetachstate(pthread_attr_t* attr,int detachstate); 3 int pthread_attr_getdetachstate(const pthread_attr_t* attr,int detachstate); 4 int pthread_attr_setschedpolicy(pthread_attr_t*attr,int policy); 5 int pthread_attr_getschegpolicy(const pthread_attr_t* attr,int policy); 6 int pthread_attr_setschedparam(pthread_attr_t* attr,struct sched_param* param); 7 int pthread_attr_getschedparam(const pthread_attr_t* attr,struct sched_param* param); 8 int pthread_attr_setinheritsched(pthead_attr_t* attr, int inherit); 9 int pthread_attr_getinheritsched(const pthread_attr_t* attr,int* inhert); 10 int pthread_attr_setscope(pthread_attr_t* attr,int scope); 11 int pthread_attr_getscope(const pthread_attr_t* attr ,int * scope); 12 int pthread_attr_setstacksize(pthread_attr_t* attr,int scope); 13 int pthread_attr_getstacksize(const pthread_attr_t* attr,int* scope);
可见线程可以使用的属性很多,但是通常不需要设置太多的属性就可以正常工作。
? detachedstate:这个属性允许我们无需对线程进行重新合并。与大多数_set类函数一样,它以一个属性指针和一个标志为参数来确定需要的状态。pthread_attr_setdetachstate函数可能用到的两个标志分别是PTHREAD_CREATE_JOINABLE和PTHREAD_CREATE_DETACHED。这个属性的默认标志值是PTHREAD_CREATE_JOINABLE,所以可以允许两个线程重新合并。如果标志设置为PTHREAD_CREATE_DETACHED,就不能调用pthread_join来获得另一个线程的退出状态。
? schedpolicy:这个属性控制线程的调度方式。它的取值可以是SCHED_OTHER、SCHED_RP和SCHED_FIFO。这个属性的默认值为SCHED_OTHER。另外两种调度方式只能用于以超级用户权限运行的进程,因为它们都具备实时调度的功能,但在行为上略有区别。SCHED_RP使用循环(round-robin)调度机制,而SCHED_FIFO使用“先进先出”策略。
? schedparam:这个属性是和schedpolicy属性结合使用的,它可以对以SCHED_OTHER策略运行的线程的调度进行控制。
? inheritsched:这个属性可取两个值:PTHREAD_EXPLICIT_SCHED和PTHREAD_INHERIT_SCHED。它的默认取值是PTHREAD_EXPLICIT_SCHED,表示调度由属性明确地设置。如果把它设置为PTHREAD_INHERIT_SCHED,新线程将沿用其创建者所使用的参数。
? scope:这个属性控制一个线程调度的计算方式。
? stacksize:这个属性控制线程创建的栈大小,单位为字节。它属于POSIX规范中的“可选”部分,只有在定义了宏_POSIX_THREAD_ATTR_STACKSIZE的实现版本中才支持。Linux在实现线程时,默认使用的栈很大,所以这个功能对Linux来说显得有些多余。
实验:脱离线程
//创建脱离线程,
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <string.h> ? void* thread_function(void* arg); char message[]={"Hello thread!"}; int thread_finished=0; ? int main() { pthread_t a_thread; int res; pthread_attr_t pattr; //初始化属性 res=pthread_attr_init(&pattr); if(res!=0) { perror("Init threadattr failed"); exit(EXIT_FAILURE); } //设置属性 res=pthread_attr_setdetachstate(&pattr,PTHREAD_CREATE_DETACHED); if(res!=0) { perror("Setting attr failed"); exit(EXIT_FAILURE); } //创建线程 res=pthread_create(&a_thread,&pattr,thread_function,(void*)message); if(res!=0) { perror("Create thread failed"); exit(EXIT_FAILURE); } //属性使用完毕后释放资源 (void)pthread_attr_destroy(&pattr); //循环,等待新线程设置结束标准;这里表明主线程和其他线程共享全局变量。 while(thread_finished!=1) { printf("Wating for thread finished\n"); sleep(1); } printf("other thread finished\n"); exit(EXIT_SUCCESS); return 0; } ? void* thread_function(void*arg) { printf("Thread is running.\nArgument is :%s\n",(char*)arg); sleep(1); printf("Second thread setting finished flag,and exiting now\n"); thread_finished=1; pthread_exit(NULL); }
线程属性:调度
另外一个可能需要修改的属性:调度。改变调度属性和设置脱离状态非常类似,可以使用sched_get_priority_max和sched_get_priority_min这两个属性来差早可用的优先级别。
实验:调度
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <string.h> ? void* thread_function(void* arg); char message[]={"Hello thread!"}; int thread_finished=0; int main() { int max_policy; int min_policy; struct sched_param sched_value; pthread_t a_thread; int res; pthread_attr_t pattr; //初始化属性 res=pthread_attr_init(&pattr); if(res!=0) { perror("Init threadattr failed"); exit(EXIT_FAILURE); } //设置脱离属性 res=pthread_attr_setdetachstate(&pattr,PTHREAD_CREATE_DETACHED); if(res!=0) { perror("Setting attr failed"); exit(EXIT_FAILURE); } //设置调度策略 res=pthread_attr_setschedpolicy(&pattr,SCHED_OTHER); if(res!=0) { perror("Set sched failed"); exit(EXIT_FAILURE); } //查找可使用的优先级 max_policy=sched_get_priority_max(SCHED_OTHER); min_policy=sched_get_priority_min(SCHED_OTHER); //设置优先级 sched_value.sched_priority=min_policy; res=pthread_attr_setschedparam(&pattr,&sched_value); if(res!=0) { perror("Set sched attr failed"); exit(EXIT_FAILURE); } //创建线程 res=pthread_create(&a_thread,&pattr,thread_function,(void*)message); if(res!=0) { perror("Create thread failed"); exit(EXIT_FAILURE); } (void)pthread_attr_destroy(&pattr); //循环,等待新线程设置结束标准;这里表明主线程和其他线程共享全局变量。 while(thread_finished!=1) { printf("Wating for thread finished\n"); sleep(1); } printf("other thread finished\n"); exit(EXIT_SUCCESS); return 0; } void* thread_function(void*arg) { printf("Thread is running.\nArgument is :%s\n",(char*)arg); sleep(4); printf("Second thread setting finished flag,and exiting now\n"); thread_finished=1; pthread_exit(NULL); }
7、取消一个线程:
请求终止的函数:
int pthread_cancle(pthread_t thread);提供一个进程标识符,就可以终止它,在主线程是如此简单,但是在被取消的线程是就不是这么简单了!!
线程可以使用pthread_setcanclestate设置自己的取消状态:
int pthread_setcanclestate(int state,int*oldstate);
第一个参数可以是PTHREAD_CANCLE_ENABLE这个值允许取消请求,PTHREAD_CANCLE_DISABLE,它的作用是忽略取消请求。oldstate指针用于获取先前的状态,没有必要的时候可以设置为NULL; 如果取消请求被接受了,线程就可以进入第二个控制层次,用pthread_setcanceltype设置取消类型。
int pthread_setcancletype(int type,int* oldtype);
type参数可以有两种取值:一个是PTHREAD_CANCEL_ASYNCHRONOUS(立即取消),它将使得在接收到取消请求后立即采取行动;另一个是PTHREAD_CANCEL_DEFERRED(延迟取消),它将使得在接收到取消请求后,一直等待直到线程执行了下述函数之一后才采取行动。具体是函数pthread_join、pthread_cond_wait、pthread_cond_timedwait、pthread_testcancel、sem_wait或sigwait。
实验:取消一个线程
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <string.h> ? char message[]={"Hello thread!"}; void* thread_function(void*arg) { int i,res; res=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);//在新创建的线程中,我们首先将取消状态设置为允许取消, if(res!=0) { perror("set cacle state failed"); exit(EXIT_FAILURE); } res=pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);//然后将取消类型设置为延迟取消 //res=pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); if(res!=0) { perror("set cancle type error"); exit(EXIT_FAILURE); } printf("Thread_Function is runing\n"); //最后,线程在循环中等待被取消 for(i=0;i<10;i++) { printf("Thread is still runing\n"); sleep(1); } pthread_exit(NULL); } ? int main() { pthread_t a_thread; int res; void* thread_res; int i; //创建线程 //以通常的方法创建了新线程后,主线程休眠一会儿(好让新线程有时间开始执行),然后发送一个取消请求。 res=pthread_create(&a_thread,NULL,thread_function,NULL); if(res!=0) { perror("Create thread error"); exit(EXIT_FAILURE); } sleep(3); printf("Canceling thread \n"); res=pthread_cancel(a_thread); if(res!=0) { perror("cancel a thread failed"); exit(EXIT_FAILURE); } printf("wating for thread to finish\n"); if(res!=0) { perror("thread join failed"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
多线程:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> ? void* thread_function(void* arg) { int my_number; int Rand; // my_number=(int)arg; my_number=*(int*)arg; printf("Thread_function runing from %d\n",my_number); Rand=1+(int)(9.0*rand()/(RAND_MAX+1.0)); ? sleep(Rand);//休眠一个随机时间 printf("Bye from %d\n",my_number); pthread_exit(NULL); } int main() { int res; pthread_t thread_id[6]; void * thread_res; int num_of_thread; for(num_of_thread=0;num_of_thread<6;num_of_thread++) { //res=pthread_create(&thread_id[num_of_thread],NULL,thread_function,(void*)num_of_thread); res=pthread_create(&thread_id[num_of_thread],NULL,thread_function,(void*)&num_of_thread); if(res==0) { sleep(1); } else { perror("Create thread fauiled"); exit(EXIT_FAILURE); } } for(num_of_thread=5;num_of_thread>=0;num_of_thread--) { res=pthread_join(thread_id[num_of_thread],&thread_res); if(res==0) { printf("Picked ip a thread \n"); } else { perror("Picedf up failed"); exit(EXIT_FAILURE); } } printf("Picede upo all\n"); printf("Done\n"); exit(EXIT_SUCCESS); }
我们创建了许多线程并让它们以随意的顺序结束执行。这个程序有一个小漏洞,如果将sleep调用从启动线程的循环中删除,它就会变得很明显。
改进:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <pthread.h> 6 ? 7 void* thread_function(void* arg) 8 { 9 int my_number; 10 int Rand; 11 my_number=(int)arg; 12 printf("Thread_function runing from %d\n",my_number); 13 Rand=1+(int)(9.0*rand()/(RAND_MAX+1.0)); 14 ? 15 sleep(Rand);//休眠一个随机时间 16 printf("Bye from %d\n",my_number); 17 pthread_exit(NULL); 18 } 19 int main() 20 { 21 int res; 22 pthread_t thread_id[6]; 23 void * thread_res; 24 int num_of_thread; 25 for(num_of_thread=0;num_of_thread<6;num_of_thread++) 26 { 27 res=pthread_create(&thread_id[num_of_thread],NULL,thread_function,(void*)num_of_thread); 28 if(res!=0) 29 { 30 perror("Create thread fauiled"); 31 exit(EXIT_FAILURE); 32 } 33 } 34 for(num_of_thread=5;num_of_thread>=0;num_of_thread--) 35 { 36 res=pthread_join(thread_id[num_of_thread],&thread_res); 37 if(res==0) 38 { 39 printf("Picked ip a thread \n"); 40 } 41 else 42 { 43 perror("Picedf up failed"); 44 exit(EXIT_FAILURE); 45 } 46 } 47 printf("Picede upo all\n"); 48 printf("Done\n"); 49 exit(EXIT_SUCCESS); 50 }
以上是关于线程 属性取消线程多线程的主要内容,如果未能解决你的问题,请参考以下文章