例如主线程继续为用户提供服务的同时创建第二个线程
这个线程的作用是将用户正在编辑的数据进行备份存储
那么备份结束之后第二个线程就可以字节终止
没必要再回到主线程中区
称这样的线程为脱离线程,可以通过修改属性或者调用pthread_detach的方法来创建
这里我们从属性的角度研究脱离线程
1 #include <pthread.h> 2 int pthread_atte_init(pthread_attr_t * attr);
函数的作用是初始化一个线程属性对象
对应的回收函数是pthread_attr_destory,目的是对属性对象进行清理和回收
一旦对象被回收了,除非被重新初始化,否则不能再次使用它。
初始化线程属性对象后,可以使用很多其他的函数来设置不同的属性行为
1 int pthread_attr_setdetachstate(pthread_attr_t * attr, int detachstate); 2 int pthread_attr_getdetachstate(const pthread_attr_t * attr, int * detachstate);
//set函数可能用到的两个标志是PTHREAD_CREATE_JOINABLE和PTHREAD_CREATE_DETACHED
//默认是前者,允许两个线程重新结合,要是后者的话,不能使用pthread_join来恢复另外一个线程的退出状态
1 int pthread_attr_setschedpolicy(pthread_attr_t * attr, int policy); 2 int pthread_attr_getchedpolicy(const pthread_attr_t * attr, int * policy);
//控制线程的调度方式,SCHED_OTHER,SCHED_RP,SCHED_FIFO默认的是第一个。
1 int pthread_attr_setschedparm(pthread_attr_t * attr, const struct sched_param * param); 2 int pthread_attr_getschedparam(const pthread_attr_t * attr, struct sched_param * param);
//这个函数可以对上面的线程的调度进行控制
1 int pthread_attr_setinheritsched(pthread_attr_t * attr, int inherit); 2 int pthread_attr_getinheritsched(const pthread_attr_t * attr, int * inherit);
//取值有两个,PTHREAD_EXPLICIT_SCHED和PTHREAD_INHERIT_SCHED.默认的是第一个
//表示时间分配由属性明确的设置,要是第二个的话,新线程将沿用其创建者使用的参数
1 int pthread_attr_setscope(pthread_attr_t * attr, int scope); 2 int pthread_attr_getscope(const pthread_attr_t * attr, int *scope);
//控制一个线程调度的计算方式,取值目前是唯一的就是PTHREAD_SCOPE_SYSTEM
1 int pthread_attr setstacksize(pthread_attr_t * attr, int scope); 2 int pthread_attr_getstacksize(const pthread_attr_t * attr, int * scope);
//这个属性控制线程创建的栈的大小,单位是字节,属于POSIX可选的规范。
//linux实现的时候默认的栈都很大,这个功能对linux来说有些多余
设置脱离状态属性程序:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <pthread.h> 5 6 void *thread_function(void *arg); 7 8 char message[] = "Hello World"; 9 int thread_finished = 0; 10 11 int main() { 12 int res; 13 pthread_t a_thread; 14 void *thread_result; 15 pthread_attr_t thread_attr; 16 17 res = pthread_attr_init(&thread_attr);//初始化一个线程属性对象 18 if (res != 0) { 19 perror("Attribute creation failed"); 20 exit(EXIT_FAILURE); 21 } 22 23 res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); 24 if (res != 0) { 25 perror("Setting detached attribute failed"); 26 exit(EXIT_FAILURE); 27 }//设置属性对象为两个对象不重新结合 28 29 res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)message); 30 if (res != 0) { 31 perror("Thread creation failed"); 32 exit(EXIT_FAILURE); 33 }//创建一个新线程,新线程去执行定义的函数 34 35 (void)pthread_attr_destroy(&thread_attr);//对属性对象进行清理和回收 36 while(!thread_finished) { 37 printf("Waiting for thread to say it's finished... ");//先打印一次,去执行新线程 38 sleep(1);//第一秒打印一句,第二秒打印一次,第三秒打印一次 39 } 40 printf("Other thread finished, bye! "); 41 exit(EXIT_SUCCESS); 42 } 43 44 void *thread_function(void *arg) { 45 printf("thread_function is running. Argument was %s ", (char *)arg); 46 sleep(4);//打印一句话,然后等待,第四秒打印下面的一句,全局变量置位 47 printf("Second thread setting finished flag, and exiting now "); 48 thread_finished = 1; 49 pthread_exit(NULL); 50 }
程序的执行的效果:
1 jason@t61:~/c_program/544977-blp3e/chapter12$ gcc thread5.c -o thread5 -lpthread 2 jason@t61:~/c_program/544977-blp3e/chapter12$ ./thread5 3 Waiting for thread to say it's finished... 4 thread_function is running. Argument was Hello World 5 Waiting for thread to say it's finished... 6 Waiting for thread to say it's finished... 7 Waiting for thread to say it's finished... 8 Second thread setting finished flag, and exiting now 9 Other thread finished, bye! 10 jason@t61:~/c_program/544977-blp3e/chapter12$
线程属性--调度
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <pthread.h> 5 6 void *thread_function(void *arg); 7 8 char message[] = "Hello World"; 9 int thread_finished = 0; 10 11 int main() { 12 int res; 13 pthread_t a_thread; 14 void *thread_result; 15 pthread_attr_t thread_attr; 16 17 int max_priority; 18 int min_priority; 19 struct sched_param scheduling_value; 20 21 res = pthread_attr_init(&thread_attr); 22 if (res != 0) { 23 perror("Attribute creation failed"); 24 exit(EXIT_FAILURE); 25 }//初始化一个线程属性对象 26 27 28 res = pthread_attr_setschedpolicy(&thread_attr, SCHED_OTHER); 29 if (res != 0) { 30 perror("Setting schedpolicy failed"); 31 exit(EXIT_FAILURE); 32 }//设置调度策略 33 34 35 res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); 36 if (res != 0) { 37 perror("Setting detached attribute failed"); 38 exit(EXIT_FAILURE); 39 }//设置为脱离状态 40 41 42 res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)message); 43 if (res != 0) { 44 perror("Thread creation failed"); 45 exit(EXIT_FAILURE); 46 }//创建线程 47 48 49 max_priority = sched_get_priority_max(SCHED_OTHER); 50 min_priority = sched_get_priority_min(SCHED_OTHER);//查找允许的优先范围 51 scheduling_value.sched_priority = min_priority; 52 res = pthread_attr_setschedparam(&thread_attr, &scheduling_value);//对调度策略进行控制 53 if (res != 0) { 54 perror("Setting schedpolicy failed"); 55 exit(EXIT_FAILURE); 56 } 57 58 59 (void)pthread_attr_destroy(&thread_attr);//对属性对象进行清理和回收 60 61 62 while(!thread_finished) { 63 printf("Waiting for thread to say it's finished... "); 64 sleep(1); 65 } 66 printf("Other thread finished, bye! "); 67 exit(EXIT_SUCCESS); 68 } 69 70 void *thread_function(void *arg) { 71 printf("thread_function is running. Argument was %s ", (char *)arg); 72 sleep(4); 73 printf("Second thread setting finished flag, and exiting now "); 74 thread_finished = 1; 75 pthread_exit(NULL); 76 }
程序的执行效果:
1 jason@t61:~/c_program/544977-blp3e/chapter12$ ./thread6 2 Waiting for thread to say it's finished... 3 thread_function is running. Argument was Hello World 4 Waiting for thread to say it's finished... 5 Waiting for thread to say it's finished... 6 Waiting for thread to say it's finished... 7 Second thread setting finished flag, and exiting now 8 Other thread finished, bye! 9 jason@t61:~/c_program/544977-blp3e/chapter12$
取消一个线程:
线程可以在被要求终止时改变其行为
1 #include <pthread.h> 2 int pthread_cancel(pthread_t thread);
提供一个线程标识符就可以发送请求取消它
1 #include <pthread.h>//线程用这个函数可以自己设置自己的取消状态 2 int pthread_setcancelstate(int state, int * oldstate);
第一个参数可以是PTHREAD_CANCEL_ENABLE这个值允许线程接收取消请求
或者是PTHREAD_CANCEL_DISABLE作用忽略取消请求
oldstate指针用于获取先前的取消状态.默认enable
1 #include <pthread.h> 2 int pthread_setcanceltype(int type, int * oldtype);
type可以有两种取值,一个是PTHREAD_CANCEL_ASYNCHRONOUS使得在接收到取消请求时立即采取行动
PTHREAD_CANCEL_DEFERED使得在接收到取消请求后,一致等待直到线程执行了
pthread_join,pthread_cond_wait
pthread_cond_timewait,pthread_testcancel
sem_wait,sigwait
其中之一后才采取行动.默认defered
取消一个线程例程:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <pthread.h> 5 6 void *thread_function(void *arg); 7 8 int main() { 9 int res; 10 pthread_t a_thread; 11 void *thread_result; 12 13 res = pthread_create(&a_thread, NULL, thread_function, NULL); 14 if (res != 0) { 15 perror("Thread creation failed"); 16 exit(EXIT_FAILURE); 17 } 18 19 sleep(3);//让新建线程执行三秒 20 printf("Canceling thread... "); 21 res = pthread_cancel(a_thread); 22 if (res != 0) { 23 perror("Thread cancelation failed"); 24 exit(EXIT_FAILURE); 25 } 26 27 printf("Waiting for thread to finish... "); 28 res = pthread_join(a_thread, &thread_result); 29 if (res != 0) { 30 perror("Thread join failed"); 31 exit(EXIT_FAILURE); 32 } 33 34 exit(EXIT_SUCCESS); 35 } 36 37 void *thread_function(void *arg) { 38 int i, res, j; 39 res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 40 if (res != 0) { 41 perror("Thread pthread_setcancelstate failed"); 42 exit(EXIT_FAILURE); 43 }//允许 44 45 res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); 46 if (res != 0) { 47 perror("Thread pthread_setcanceltype failed"); 48 exit(EXIT_FAILURE); 49 }//异步 50 51 printf("thread_function is running "); 52 for(i = 0; i < 10; i++) { 53 printf("Thread is still running (%d)... ", i); 54 sleep(1); 55 }//线程循环等待被取消 56 pthread_exit(0); 57 }
程序的执行的效果:
1 jason@t61:~/c_program/544977-blp3e/chapter12$ gcc thread7.c -o thread7 -lpthread 2 jason@t61:~/c_program/544977-blp3e/chapter12$ ./thread7 3 thread_function is running 4 Thread is still running (0)... 5 Thread is still running (1)... 6 Thread is still running (2)... 7 Canceling thread... 8 Waiting for thread to finish... 9 jason@t61:~/c_program/544977-blp3e/chapter12$
多线程:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <pthread.h> 5 6 #define NUM_THREADS 6 7 8 void *thread_function(void *arg); 9 10 int main() { 11 int res; 12 pthread_t a_thread[NUM_THREADS]; 13 void *thread_result; 14 int lots_of_threads; 15 16 for(lots_of_threads = 0; lots_of_threads < NUM_THREADS; lots_of_threads++) { 17 //做个大循环//循环刚才的新建过程 18 res = pthread_create(&(a_thread[lots_of_threads]), NULL, thread_function, (void *)&lots_of_threads); 19 if (res != 0) { 20 perror("Thread creation failed"); 21 exit(EXIT_FAILURE); 22 }//创建进程 23 sleep(1);//休眠让新建进程执行 24 } 25 printf("Waiting for threads to finish... ");//6个新的线程新建完成之后 26 for(lots_of_threads = NUM_THREADS - 1; lots_of_threads >= 0; lots_of_threads--) { 27 res = pthread_join(a_thread[lots_of_threads], &thread_result); 28 if (res == 0) { 29 printf("Picked up a thread "); 30 }//等待回收第6个。然后是第5个 31 else { 32 perror("pthread_join failed"); 33 } 34 } 35 printf("All done ");//都完成之后打印退出 36 exit(EXIT_SUCCESS); 37 } 38 39 void *thread_function(void *arg) { 40 int my_number = *(int *)arg; 41 int rand_num; 42 43 printf("thread_function is running. Argument was %d ", my_number);//打印一句话 44 rand_num=1+(int)(9.0*rand()/(RAND_MAX+1.0)); 45 sleep(rand_num);//休眠随机数秒 46 printf("Bye from %d ", my_number); 47 pthread_exit(NULL); 48 }
执行效果:
1 jason@t61:~/c_program/544977-blp3e/chapter12$ gcc thread8.c -o thread8 -lpthread 2 jason@t61:~/c_program/544977-blp3e/chapter12$ ./thread8 3 thread_function is running. Argument was 0 4 thread_function is running. Argument was 1 5 thread_function is running. Argument was 2 6 thread_function is running. Argument was 3 7 thread_function is running. Argument was 4 8 Bye from 1 9 thread_function is running. Argument was 5 10 Waiting for threads to finish... 11 Bye from 5 12 Picked up a thread 13 Bye from 0 14 Bye from 2 15 Bye from 3 16 Bye from 4 17 Picked up a thread 18 Picked up a thread 19 Picked up a thread 20 Picked up a thread 21 Picked up a thread 22 All done//执行三次打印的顺序都是一样的!
参考文献:linux 程序设计
date:2015年 06月 30日 星期二 20:40:07 CST