`
guanhuaing
  • 浏览: 1197526 次
文章分类
社区版块
存档分类
最新评论

POSIX线程-(五)

 
阅读更多


线程属性

当我们第一次了解线程时,我们并没有讨论线程属性的问题。我们现在会进行讨论。线程有许多我们可以控制的属性。然而,在这里我们只讨论那些我们最需要的线程属性。其他属性的详细信息可以在手册中了解到。

在所有我们前面的例子中,我们不得不在允许程序退出之前使用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_setscope(pthread_attr_t *attr, int scope);
int pthread_attr_getscope(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标记来允许主线程检测子线程是否已经结束,并且显示出线程仍共享变量。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <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("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 *)message);
if(res != 0)
{
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);
while(!thread_finished)
{
printf("Waiting for thread to say it's finished.../n");
sleep(1);
}
printf("Othread 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);
printf("Second thread setting finished flag, and exiting now/n");
thread_finished = 1;
pthread_exit(NULL);
}

正如我们所看到的,设置分离状态允许第二个线程独立完成,而不需要主线程来等待第二个线程。

工作原理

两个重要的代码段为:

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
*)message);

并且为了完整性,当我们使用完这个属性之后要销毁这个属性:

pthread_attr_destroy(&thread_attr);

分享到:
评论

相关推荐

    i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z

    MinGW-W64的32位安装包:i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z ,支持GCC8.1.0,线程模型为posix,异常处理模型为dwarf, 解压后即可使用。 mingw-w64 版本选择方法: 32位系统选择i686, 64位系统选择x86_...

    i686-7.3.0-release-posix-dwarf-rt_v5-rev0.7z

    线程模型:win32 : 没有C ++ 11多线程特性, posix : 支持C ++ 11多线程特性; 异常处理模型:32位系统推荐dwarf,64位系统推荐seh。seh 是新发明的,而 sjlj 则是古老的。seh 性能比较好,但不支持 32位, sjlj 稳定...

    POSIX线程编程指南

    POSIX线程编程指南 这是一个关于 Posix 线程编程的专栏。作者在阐明概念的基础上,将向您详细讲述Posix 线程库API

    POSIX线程编程指南.pdf

    POSIX线程编程指南.pdfPOSIX线程编程指南.pdfPOSIX线程编程指南.pdfPOSIX线程编程指南.pdf

    POSIX线程编程指南(合集)

    POSIX线程(Pthread)编程指南

    posix线程详解.pdf(中文版)

    关于POSIX线程的讲解,供学习和工作使用,值得下载。

    Posix线程编程指南.pdf

    Posix线程编程指南 线程 线程编程 linux

    posix多线程程序设计源码

    posix多线程程序设计源码 posix多线程程序设计源码 posix多线程程序设计源码 posix多线程程序设计源码

    IBM POSIX 线程编程资料

    这是将网上收集的IBM线程编程资料整理成了一个chm文件,便于使用。内容包括UNIX线程编程指南和详解部分,适合学习POSIX线程编程技术的人员使用。

    Posix线程(经典)

    posix多线程相关的函数介绍,与POSIX多线程程序设计中文版一起看,相得益彰

    多线程-共享内存

    Posix多线程-共享内存

    POSIX多线程程序设计

    内容提要, 本书深入描述了IEEE的开放系统接口标准-POSIX线程,通常称为Pthreads标准。本, 书首先解释了线程的基本概念,包括异步编程、线程的生命周期和同步机制;然后讨论了, 一些高级话题,包括属性对象、线程私有...

    mingw64-8.1.0-release-posix-seh-rt_v6-rev0离线安装包.rar

    windows中mingw64-8.1.0-release-posix离线安装包,解压即可使用,内置的gcc版本为8.1.0,线程模型为posix,支持C+11/C11的语法与库。 免去了在线安装缓慢的问题。 可以编译 win32 和 win64程序。

    Posix线程编程指南

    Posix线程编程指南 posix标准解释

    POSIX多线程程序设计.pdf

    《POSIX多线程程序设计》深入描述了IEEE的开放系统接口标准——POSIX线程,通常称为Pthreads标准。本书首先解释了线程的基本概念,包括异步编程、线程的生命周期和同步机制;然后讨论了一些高级话题,包括属性对象、...

    posix线程详解 线程 进程

    POSIX(可移植操作系统接口)线程是提高代码响应和性能的有力手段。在本系列中,Daniel Robbins 向您精确地展示在编程中如何使用线程。其中还涉及大量幕后细节,读完本系列文章,您完全可以运用 POSIX 线程创建多...

    Linux多线程编程的基本的函数-Posix线程编程指南

    Linux多线程编程的基本的函数-Posix线程编程指南

Global site tag (gtag.js) - Google Analytics