2011-11-06 wcdj
BLP 4th P.431
在多线程程序中,通常在程序退出之前用pthread_join对线程再次进行同步,目的是让线程向创建它的主线程返回数据。但是,在某些情况下,我们既不需要第二个线程向主线程返回信息,也不想让主线程等待它的结束。例如,假设我们在主线程继续为用户提供服务的同时创建了第二个线程,新线程的作用是将用户正在编辑的数据文件进行备份存储,在备份工作结束后,第二个线程就可以直接终止了,它没有必要再回到主线程中。
我们可以创建这一类型的线程,它们被称为“ 脱离线程”( detached thread)。可以通过修改线程的属性或调用pthread_detach的方法来创建它们。在这里主要介绍通过修改线程的属性的方法。
主要的函数:
#include <pthread.h>
(1) int pthread_attr_init(pthread_attr_t *attr);
返回值:成功返回0,失败返回错误代码。
(2) 回收函数 pthread_attr_destory, 目的是对属性对象进行清理和回收。一旦对象被回收了,除非它被重新初始化,否则就不能被再次使用。
(3) 初始化一个线程属性对象后,可以调用许多其他的函数来设置不同的属性行为。(完整的函数列表见手册页,通常位于pthread.h条目下)。可以使用的线程属性非常多,但幸运的是,通常不需要设置太多属性就可以让程序正常工作。
一些主要的 属性介绍如下:
[1] detachedstate
这个属性允许我们无需对线程进行重新合并。与大多数_set类函数一样,它以一个属性指针和一个标志为参数来确定需要的状态。pthread_attr_setdetachstate函数可能用到的两个标志分别是:PTHREAD_CREATE_JOINABLE 和 PTHREAD_CREATE_DETACHED。这个属性的默认标志是 PTHREAD_CREATE_JOINABLE,所以可以允许两个线程重新合并。如果标志设置为 PTHREAD_CREATE_DETACHED,就不能调用 pthread_join来获得另一个线程的退出状态。
[2] schedpolicy
这个属性控制线程的调度方式。它的取值可以是 SCHED_OTHER、SCHED_RP 和 SCHED_FIFO。这个属性的默认值为 SCHED_OTHER。另外两种调度方式只能用于以超级用户权限运行的进程,因为它们都具备实时调度的功能,但在行为上略有区别。SCHED_RP 使用循环(round-robin)调度机制,而SCHED_FIFO 使用“先进先出”策略。
例子:设置脱离状态属性
BLP 4th P.431
线程的属性
在多线程程序中,通常在程序退出之前用pthread_join对线程再次进行同步,目的是让线程向创建它的主线程返回数据。但是,在某些情况下,我们既不需要第二个线程向主线程返回信息,也不想让主线程等待它的结束。例如,假设我们在主线程继续为用户提供服务的同时创建了第二个线程,新线程的作用是将用户正在编辑的数据文件进行备份存储,在备份工作结束后,第二个线程就可以直接终止了,它没有必要再回到主线程中。
我们可以创建这一类型的线程,它们被称为“ 脱离线程”( detached thread)。可以通过修改线程的属性或调用pthread_detach的方法来创建它们。在这里主要介绍通过修改线程的属性的方法。
主要的函数:
#include <pthread.h>
(1) int pthread_attr_init(pthread_attr_t *attr);
返回值:成功返回0,失败返回错误代码。
(2) 回收函数 pthread_attr_destory, 目的是对属性对象进行清理和回收。一旦对象被回收了,除非它被重新初始化,否则就不能被再次使用。
(3) 初始化一个线程属性对象后,可以调用许多其他的函数来设置不同的属性行为。(完整的函数列表见手册页,通常位于pthread.h条目下)。可以使用的线程属性非常多,但幸运的是,通常不需要设置太多属性就可以让程序正常工作。
一些主要的 属性介绍如下:
[1] detachedstate
这个属性允许我们无需对线程进行重新合并。与大多数_set类函数一样,它以一个属性指针和一个标志为参数来确定需要的状态。pthread_attr_setdetachstate函数可能用到的两个标志分别是:PTHREAD_CREATE_JOINABLE 和 PTHREAD_CREATE_DETACHED。这个属性的默认标志是 PTHREAD_CREATE_JOINABLE,所以可以允许两个线程重新合并。如果标志设置为 PTHREAD_CREATE_DETACHED,就不能调用 pthread_join来获得另一个线程的退出状态。
[2] schedpolicy
这个属性控制线程的调度方式。它的取值可以是 SCHED_OTHER、SCHED_RP 和 SCHED_FIFO。这个属性的默认值为 SCHED_OTHER。另外两种调度方式只能用于以超级用户权限运行的进程,因为它们都具备实时调度的功能,但在行为上略有区别。SCHED_RP 使用循环(round-robin)调度机制,而SCHED_FIFO 使用“先进先出”策略。
例子:设置脱离状态属性
首先创建一个线程属性,将其设置为脱离状态,然后用这个属性创建一个线程。子线程结束时,它照常调用pthread_exit,但这次,原先的线程不再等待与它创建的子线程重新合并。主线程通过一个简单的 thread_finished 标志来检测子线程是否已经结束,并显示线程之间仍然共享着变量。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg);
char msg[] = "hello, wcdj!";
int thread_finished = 0;
int main()
{
int res;
pthread_t a_thread;
pthread_attr_t thread_attr;
res = pthread_attr_init(&thread_attr);
if (res != 0)
{
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (res != 0)
{
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)msg);
if (res != 0)
{
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);// free
while(!thread_finished)
{
printf("Waiting for thread to say it's finished...\n");
sleep(1);// sleep 1 second
}
printf("Other thread finished, bye!\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(4);// sleep 4 seconds
printf("Second thread setting finished flag, and exiting now\n");
thread_finished = 1;// flag
pthread_exit(NULL);
}
/*
gerryyang@wcdj:~/test> gcc -D_REENTRANT -o thread5 thread5.c -lpthread
gerryyang@wcdj:~/test> ./thread5
Waiting for thread to say it's finished...
thread_function is running. Argument was hello, wcdj!
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Second thread setting finished flag, and exiting now
Other thread finished, bye!
gerryyang@wcdj:~/test>
*/