posix thread,
当我们第一次学习线程时,我们没有讨论线程属性。我们现在将进行讨论。线程有许多我们可以控制的属性。但是,这里我们只讨论那些我们最需要的线程属性。其他属性的详细信息可以在手册中找到。
在我们之前的所有例子中,在允许程序退出之前,我们必须使用pthread_join来重新同步我们的线程。如果我们想让一个线程将数据返回给创建它的线程,我们需要这样做。有时候我们不需要第二个线程向主线程返回信息,也不希望主线程等待第二个线程。
假设我们创建第二个线程来备份正在编辑的数据文件的副本,而主线程继续为用户服务。当备份完成时,第二个线程简单地退出,不需要与主线程聚合。
我们可以创建这样的线程。它们被称为分离线程,我们可以通过修改线程属性或一致地调用pthread_detach来创建这样的线程。因为我们想在这里演示线程属性,所以我们将使用前一种方法。
我们需要的最重要的函数是pthread_attr_init,它可以初始化一个线程属性对象。
#include pthread.h
int pthread _ attr _ init(pthread _ attr _ t * attr);
同样,如果成功,它将返回0,如果失败,它将返回一个错误代码。
还有一个销毁函数:pthread_attr_destroy。此功能的目的是允许清除属性对象。一旦对象被销毁,该属性对象在初始化之前不能再次使用。
当我们有一个初始化的线程属性时,我们可以调用许多额外的函数来设置不同的属性行为。我们在这里列出了一些主要函数,但是我们只知道其中的两个:
int pthread _ attr _ setdetachstate(pthread _ attr _ t * attr,int detachstate);
int pthread _ attr _ getdetachstate(const pthread _ attr _ t * attr,int * detachstate);
int pthread _ attr _ setschedpolicy(pthread _ attr _ t * attr,int policy);
int pthread _ attr _ getschedpolicy(const pthread _ attr _ t * attr,int * policy);
int pthread _ attr _ setschedparam(pthread _ attr _ t * attr,const struct sched_param
* param);
int pthread _ attr _ getschedparam(const pthread _ attr _ t * attr,struct sched_param
* param);
int pthread _ attr _ setinheritsched(pthread _ attr _ t * attr,int inherit);
int pthread _ attr _ getinheritsched(const pthread _ attr _ t * attr,int * inherit);
int pthread _ attr _ set scope(pthread _ attr _ t * attr,int scope);
int pthread _ attr _ get scope(const pthread _ attr _ t * attr,int * scope);
int pthread _ attr _ setstacksize(pthread _ attr _ t * attr,int scope);
int pthread _ attr _ getstacksize(const pthread _ attr _ t * attr,int * scope);
正如我们所看到的,有许多属性我们可以使用,但幸运的是,我们通常不会使用其中的大部分。
Detachstate:这个属性允许我们避免线程重新聚合的需要。像大多数_set函数一样,它将一个指向属性的指针和一个确定所需状态的标志作为参数。pthread_attr_setdetachstate函数的两个可能的标记值是PTHREAD_CREATE_JOINABLE和PTHREAD_CRATE_DETACHED。默认情况下,属性值是PTHREAD_CREATE_JOINABLE,这样我们就可以允许两个线程重新聚合。如果状态设置为PTHREAD_CRATE_DETACHED,我们就不能调用pthread_joi来恢复另一个线程的退出状态。
Schedpolicy:该属性控制如何调度线程。选项有SCHED_OTHER、SCHED_RR和SCHED_FIFO。默认情况下,属性值为SCHED_OTHER。其他两种调度类型仅在以超级用户权限运行时可用,因为它们都有实时调度,但它们的行为略有不同。SCHED_RR使用循环调度,而SCHED_FIFO使用先进先出策略。对这些属性的讨论超出了本书的范围。
Schedparam:这是schedpolicy的合作伙伴,它允许我们控制使用SCHED_OTHER策略运行的线程的调度。我们将在本章后面看到一个使用这个参数的例子。
Inheritsched:这个属性有两个可能的值:PTHREAD_EXPLICIT_SCHED和PTHREAD_INHERIT_SCHED。默认情况下,属性值为PTHREAD_EXPLICIT_SCHED,这意味着调度是通过属性显示来设置的。通过将其设置为PTHREAD_INHERIT_SCHED,新线程将使用其创建者线程使用的参数。
Scope:该属性控制如何计算线程的调度。目前Linux只支持PTHREAD_SCOPE_SYSTEM,这里就不讨论这个特性了。
Stacksize:该属性控制线程创建堆栈的大小,以字节为单位设置。这是规范的“可选”部分,仅在定义了_POSIX_THREAD_ATTR_STACKSIZE的实现中受支持。Linux默认使用大堆栈来实现线程,所以这个特性在Linux上通常很丰富。
测试-设置分离状态属性。
作为我们分离线程的一个例子,thread5.c,我们创建了一个线程属性,将其设置为分离属性,然后使用这个属性创建一个线程。现在,当子线程完成时,他以正常方式调用pthread_exit函数。但是,这一次原始线程不再等待与他创建的线程重新聚合。我们使用一个简单的thread_finished标记来允许主线程检测子线程是否已经结束,并显示线程仍然共享变量。
#包含stdio.h
#包含stdlib.h
#包含字符串. h
#包括unistd.h
#include pthread.h
void * thread _ function(void * arg);
char message[]= Hello World ;
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(属性创建失败);
退出(EXIT _ FAILURE);
}
RES=PTHREAD _ attr _ setdetachstate(thread _ attr,PTHREAD _ CREATE _ DETACHED);
if(res!=0)
{
perror(“设置分离的属性失败”);
退出(EXIT _ FAILURE);
}
res=pthread_create( a_thread,thread_attr,thread_function,(void *)message);
if(res!=0)
{
perror(“线程创建失败”);
退出(EXIT _ FAILURE);
}
(void)pthread _ attr _ destroy(thread _ attr);
而(!线程_已完成)
{
printf(等待线程说完成./n’);
睡眠(1);
}
printf( oth thread线程完成,拜拜!/n’);
退出(EXIT _ SUCCESS);
}
void *thread_function
{
printf(thread_function正在运行。参数是%s/n ,(char *)arg);
睡眠(4);
printf(第二线程设置完成标志,现在退出/n );
thread _ finished=1;
pthread_exit(空);
}
正如我们所看到的,设置分离状态允许第二个线程独立完成,而无需主线程等待第二个线程。
两个重要的代码段是:
pthread _ attr _ t thread _ attr
RES=pthread _ attr _ init(thread _ attr);
if (res!=0) {
perror(属性创建失败);
退出(EXIT _ FAILURE);
}
这将声明一个线程属性并初始化它。另一个代码是:
RES=PTHREAD _ attr _ setdetachstate(thread _ attr,PTHREAD _ CREATE _ DETACHED);
if (res!=0) {
perror(“设置分离的属性失败”);
退出(EXIT _ FAILURE);
}
这段代码将属性值设置为分离状态。
另一个区别是创建一个线程,在那里传递属性地址。
res=pthread_create( a_thread,thread_attr,thread_function,(void
*)消息);
为了完整起见,当我们使用完这个属性时,我们需要销毁这个属性:
pthread _ attr _ destroy(thread _ attr);
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。