多线程程序设计2

来源:互联网 发布:国内域名资源分布状况 编辑:程序博客网 时间:2024/04/28 09:41

 

说明:只供学习交流,转载请注明出处

 

四,线程属性

Linux系统中,每个线程都拥有一个与之相关的属性来表明该线程的特性。而一个线程属性可能与多个线程相关,描述这些线程的共有特性。在前面的实例中,调用pthread_create函数创建新的线程时,对第二个参数属性都指定了NULL,这表示创建的线程的属性取默认值,代码如下:

      ret= pthread_create(&tid2, NULL, thread_fun, (void *)&info2);

      if(ret == -1)

      {

           perror("Cannotcreate new pthread");

           return(1);

      }

…….

但在某些情况下,希望创建出的线程具有一些特殊的属性,这时就需要对线程属性进行设置或修改。如果使用线程的属性对象,首先必须初始化该对象。对线程属性对象初始化的函数是pthread_attr_init函数,该函数的具体信息如下表所示:

pthread_attr_init函数

 

头文件

#include <pthread.h>

函数原型

int pthread_attr_init(pthread_attr_t  *attr);

返回值

成功

失败

是否设置errno

0

0

说明:pthread_attr_init函数用于使用参数attr中的属性来初始化线程属性对象。该函数必须在pthread_create函数之前调用。pthread_attr_t结构体定义如下:

typedef struct

{

       int __detachstat;

       int __schedpolicy;

       struct sched_param __schedparam;

       int __inheritsched;

       int __scope;

       size_t __guardsize;

       int __stackaddr_set;

        void *__stackaddr;

       unsigned long int __stacksize;

}pthread_attr_t;

__detachstate:线程的分离状态,默认取值为PTHREAD_CREATE_JOINABLE。非分离的线程可以与其他线程连接。直到线程调用pthread_join函数或创建线程的进程退出,线程的资源是不会被释放的。

__schedpolicy:线程调度策略,默认取值为SHED_OTHER,表明线程调度是由系统决定的。

__schedparam:线程的调度参数,默认取值为0,表明调度的优先级由系统决定。

__inheritsched:线程的继承性,默认取值为PTHREAD_EXPLICIT_SCHED,表明是否从父线程处继承调度属性。

__scope:线程作用域,默认值为PTHREAD_SCOPE_SYSTEM,表明线程调度范围是在同一个进程的所有线程间,还是在系统所有进程间。

__stackaddr:线程堆栈位置。

__stacksize:线程堆栈大小。

 

错误信息:

ENOMEM:没有足够的内存用于初始化线程属性对象。

 

 

设置和获得线程分离状态:

线程的分离状态将决定线程如何结束。在默认情况下,创建出的线程是处于非分离状态的,这种线程在进程没有退出之前,不会释放线程所占用的资源。非分离线程可以通过调用前面介绍的pthread_join函数来等待其他线程的结束。这样线程在结束之后会释放自己占用的资源。处于分离状态的线程会在线程退出时释放所占用的资源。

pthread_attr_setdetachstate函数用于设置线程属性对象中的分离状态参数,该函数的具体信息如下表所示:

pthread_attr_setdetachstate函数

 

头文件

#include <pthread.h>

函数原型

int  pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

返回值

成功

失败

是否设置errno

0

0

 

说明:函数pthread_attr_setdetachstate用于设置线程属性对象的分离状态。attr为指向要设置的线程属性对象的指针。detachstate参数可以取PTHREAD_CREATE_DETACHED(分离线程)和PTHREAD_CREATE_JOINABLE(非分离线程),默认情况下,detachstate参数为PTHREAD_CREATE_JOINABLE

 

错误信息:

EINVAL:参数detachstate取值非法。

 

 

pthread_attr_getdetachstate函数用于获得线程属性对象的线程分离状态取值情况,该函数的具体信息如下表:

 

pthread_attr_getdetachstate函数

 

头文件

#include <pthread.h>

函数原型

int pthread_attr_getdetachstate(

const pthread_atttr_t *attr int *detachstate);

返回值

成功

失败

是否设置errno

0

0

说明:pthread_attr_getdetachstate函数将从attr参数中获得线程的分离状态信息,并保存在detachstate指针指向的内存空间中。线程的分离状态为PTHREAD_CREATE_DETACHEDPTHREAD_CREAT_JOINABLE

 

设置和获得线程属性对象的作用域:

pthread_attr_setscope函数和pthread_attr_getscope函数用于设置或获得线程属性对象的作用域。作用域用于控制线程是在进程内还是在系统所有进程间进行调度。pthread_attr_setscope用于设置作用域,该函数的具体信息如下表:

 

 

 

 

 

 

pthread_attr_setscope函数

 

头文件

#include <pthread.h>

函数原型

int pthread_attr_setscope(pthread_attr_t  *attr,

int contentionscope);

返回值

成功

失败

是否设置errno

0

0

 

说明:在pthread_attr_setscope函数中,attr参数为指向要设置的线程属性对象的指针,contentionscope参数为作用域取值,该参数可以取PTHREAD_SCOPE_SYSTEM,表明线程是在系统调度竞争资源。而PTHREAD_SCOPE_PROCESS表示线程是在同一个进程内,是在线程间调度竞争资源。

 

错误信息:

EINVAL:参数contentionscope取值非法。

ENOTSUP:试图设置不支持的属性值。

 

 

 

pthread_attr_getscope函数的具体信息如下表:

pthread_attr_getscope函数

 

头文件

#include <pthread.h>

函数原型

int pthread_attr_getscope(const  pthread_attr_t *attr, int *contentionscope);

返回值

成功

失败

是否设置errno

0

0

说明:pthread_attr_getscope函数将从attr参数中获得线程的作用域信息,并将结果保存在contentionscope指针所指向的内存空间。

 

设置和获得线程属性对象的继承性:

pthread_attr_setinheritsched函数和pthread_attr_getinheritsched函数用于设置或获得线程属性对象的继承性。所谓继承性,指的是是否从父线程处继承调度属性。Pthread_attr_setinheritsched函数的具体信息如下表所示:

 

头文件

#include <pthread.h>

函数原型

int pthread_attr_setinheritsched(pthread_attr_t  *attr, int inheritsched);

返回值

成功

失败

是否设置errno

0

非零值

说明:在pthread_attr_setinheritsched函数中,attr参数为指向要设置的线程属性对象的指针。inheristsched参数为继承性取值情况。该参数可以取如下的值:

PTHREAD_INHERIT_SCHED:新产生的线程继承创建线程的调度属性。

PTHREAD_EXPLICIT_SCHED:从线程属性对象中设置调度属性。

 

错误信息:

EINVAL:非法的inheritsched参数。

ENOTSUP:试图将线程属性设置为不支持的值。

 

pthread_attr_getinheritsched函数的具体信息如下表:

pthread_attr_getinheritsched函数

 

头文件

#include <pthread.h>

函数原型

int pthread_attr_getinheritsched

(const pthread_attr_t *attr, int  inheritsched);

返回值

成功

失败

是否设置errno

0

0

 

说明:pthread_attr_getinheritsched函数将从attr参数中获得继承性信息,并将结果保存在inheritsched指针所指向的内存空间。

 

设置和获得线程属性对象的调度策略:

pthread_attr_setschedpolicy函数和pthread_attr_getschedpolicy函数用于设置或获得线程属性中的调度策略信息。调度策略指的是线程间的资源获取策略。pthread_attr_setschedpolicy函数的具体信息如下表:

pthread_attr_setschedpolicy函数

 

头文件

#include <pthread.h>

函数原型

int pthread_attr_setschedpolicy

(pthread_attr_t *attr, int policy);

返回值

成功

失败

是否设置errno

0

0

说明:在pthread_attr_setschedpolicy函数中,attr参数为指向要设置的线程属性对象的指针。policy参数为要设置的调度策略,可以取SCHED_FIFO(先进先出)、SCHED_RR(轮转法)或SCHED_OTHER(未定义的调度策略)。

 

错误信息:

EINVAL:非法的policy参数。

ENOTSUP:试图将线程属性设置为不支持的值。

 

pthread_attr_getschedpolicy函数的具体信息如下表所示:

pthread_attr_getschedpolicy函数

 

头文件

#include <pthread.h>

函数原型

int   pthread_attr_getschedpolicy

(const pthread_attr_t *attr, int  *policy);

返回值

成功

失败

是否设置errno

0

0

 

说明:pthread_attr_getschedpolicy函数将从attr参数中获得线程调度策略信息,并将结果保存在policy指针指向的内存空间。

 

 

设置和获得线程属性对象的调度参数:

 

pthread_attr_setschedparampthread_attr_getschedparam用于设置和获得线程属性对象的调度参数。pthread_attr_setschedparam的具体信息如下表所示:

 

 

 

pthread_attr_setschedparam函数

 

头文件

#include <pthread.h>

函数原型

int   pthread_attr_setschedparam

(pthread_attr_t *attr,const struct  sched_param *param);

返回值

成功

失败

是否设置errno

0

0

说明:在pthread_attr_setschedparam函数中,attr参数为指向要设置的线程属性对象的指针。param参数为指向sched_param结构体的指针。Sched_param结构体在<sched.h>中有定义。对于SCHED_FIFOSCHED_RR调度算法,只需设置sched_param结构体中的线程调度优先级sched_priority即可。

 

错误信息:

EINVAL:非法的param参数。

ENOTSUP:试图将线程属性设置为不支持的值。

 

 

 

pthread_attr_getschedparam函数的信息如下表:

 

pthread_attr_getschedparam函数

 

头文件

#include <pthread.h>

函数原型

int   pthread_attr_getschedparam

(const pthread_attr_t attr, struct  sched_param * param);

返回值

成功

失败

是否设置errrno

0

0

 

说明:pthread_attr_getschedparam函数将从attr参数中获得线程调度参数的信息,并将结果保存在param指针所指向的sched_param类型的结构体中。

 

 

实例:

程序为通过函数来设置进程的优先级和调度算法的实例。在程序中创建了两个线程,分别执行thread_one_info函数和thread_two_info函数。具体代码如下:

#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <stdlib.h>void *thread_one_info(void){int i;for (i = 0; i < 5; i++){printf("In thread1, sleep...\n");sleep(1);}printf("Thread %ld : in thread_one_info function\n", (long)pthread_self());return (NULL);}void *thread_two_info(void){int i;for (i = 0; i < 5; i++){printf("In thread2, sleep...\n");sleep(1);}printf("Thread %ld : in thread_two_info function\n", (long)pthread_self());return (NULL);}int main(int argc, char *argv[]){pthread_t thread_id1, thread_id2;int ret;struct sched_param param1, param2;int num1;int num2;//判断参数是否符合要求,其中输入的参数将作为线程执行的优先级if ( argc != 3 ){printf("Usage : %s thread_one_priority thread_two_priority\n", argv[0]);return (1);}num1 = atoi(argv[1]);num2 = atoi(argv[2]);pthread_attr_t attr_obj1;pthread_attr_t attr_obj2;//初始化线程属性对象pthread_attr_init(&attr_obj1);pthread_attr_init(&attr_obj2);//获得线程属性对象的优先级ret = pthread_attr_getschedparam(&attr_obj1, ¶m1);if ( ret != 0 ){perror("obj1: cannot get schedule parameters");return (1);}ret = pthread_attr_getschedparam(&attr_obj2, ¶m2);if ( ret != 0 ){perror("obj2: cannot get schedule parameters");return (1);}//输出优先级信息printf("obj1: thread priority : %d\n", param1.sched_priority);printf("obj2: thread priority : %d\n", param2.sched_priority);//更改优先级param1.sched_priority = num1;param2.sched_priority = num2;printf("======Now thread priority======\n");printf("obj1: thread priority : %d\n", param1.sched_priority);printf("obj2: thread priority : %d\n", param2.sched_priority);//设置线程的优先级ret = pthread_attr_setschedparam(&attr_obj1, ¶m1);if ( ret != 0 ){perror("obj1: cannot set schedule parameters");return (1);}ret = pthread_attr_setschedparam(&attr_obj2, ¶m2);if ( ret != 0 ){perror("obj2: cannot set schedule parameters");return (-1);}//设置调度作用域ret = pthread_attr_setscope(&attr_obj1, PTHREAD_SCOPE_SYSTEM);if (ret != 0){perror("obj1: cannot set schedule scope");return (1);}ret = pthread_attr_setscope(&attr_obj2, PTHREAD_SCOPE_SYSTEM);if (ret != 0){perror("obj2: cannot set schedule scope");return (1);}//设置调度策略ret = pthread_attr_setschedpolicy(&attr_obj1, SCHED_RR);if (ret != 0){perror("obj1: Cannot set schedule scope");return (1);}ret = pthread_attr_setschedpolicy(&attr_obj2, SCHED_RR);if (ret != 0){perror("obj2: Cannot set schedule policy");return (1);}//创建新的线程ret = pthread_create(&thread_id1, &attr_obj1, (void *)thread_one_info, NULL);if (ret == -1){perror("Cannot create new thread1");return (1);}ret = pthread_create(&thread_id2, &attr_obj2, (void *)thread_two_info, NULL);if (ret == -1){perror("Cannot create new thread2");return (0);}//等待线程pthread_join(thread_id1, NULL);pthread_join(thread_id2, NULL);return (0);}运行结果:[root@localhost test]# ./pthread_attr 2 22obj1: thread priority : 0obj2: thread priority : 0======Now thread priority======obj1: thread priority : 2obj2: thread priority : 22In thread1, sleep...In thread2, sleep...In thread1, sleep...In thread2, sleep...In thread1, sleep...In thread2, sleep...In thread1, sleep...In thread2, sleep...In thread1, sleep...In thread2, sleep...Thread -1208353904 : in thread_one_info functionThread -1216746608 : in thread_two_info function[root@localhost test]#


 

 

 

 

 

 

 

 

 

 

 

 

 

 

原创粉丝点击