zoukankan      html  css  js  c++  java
  • 第10章 线程控制(2)_线程属性和线程优先级

    3. 线程属性

    3.1 线程属性结构体

    (1)pthread_attr_t结构体

     

    (2)线程属性初始化和销毁

    头文件

    #include <pthread.h>

    函数

    int pthread_attr _init(pthread_attr_t* attr); //初始化

    int pthread_attr_destroy(pthread_attr_t* attr); //销毁

    返回值

    成功返回0,否则返回错误编号

    3.2 设置和获取分离属性

    头文件

    #include <pthread.h>

    函数

    int pthread_attr _getdetachstat (const pthread_attr_t* attr, int* detachstate); //获取分离属性

    int pthread_attr_setdetachstat (const pthread_attr_t* attr, int detachstate); //设置分离属性

    返回值

    成功返回0,否则返回错误编号

    参数

    detachstate的取值:

    ①PTHREAD_CREATE_JOINABLE(默认值) //正常启动线程

    ②PTHREAD_CREATE_DETACHED         //以分离状态启动线程

    备注

    (1)以默认方式启动的线程,在线程结束后不会自动释放占用的系统资源,要在主控线程中调用pthread_join()后才会释放。

    (2)以分离状态启动的线程,在线程结束后会自动释放所占有的系统资源。

    (3)分离属性在网络通讯中使用的较多。

    【编程实验】线程分离属性

    //pthread_detach.c

    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    //线程函数
    void* th_fn(void* arg)
    {
        int i = 0;
        int sum = 0;
        for(i=1; i<=100; i++){
            sum += i;
        }
        return (void*)sum;
    }
    
    //输出线程属性
    void out_state(pthread_attr_t* attr)
    {
        int state = 0;
        //获取分离属性
        if(pthread_attr_getdetachstate(attr, &state)!=0){
            perror("getdetachstate error");
        }else{
            if(state == PTHREAD_CREATE_JOINABLE){
                printf("joinable state
    ");//正常状态启动
            }else if(state == PTHREAD_CREATE_DETACHED){
                printf("detached state
    ");//分离状态启动
            }else{
                printf("error state
    ");
            }
        }
    }
    
    int main(void)
    {
        int err;
        pthread_t default_th, detach_th;
        //定义线程属性
        pthread_attr_t attr;
        //对线程属性初始化
        pthread_attr_init(&attr);
        //输出分离属性:默认值
        out_state(&attr); 
        
        //方式1:以分离属性的默认值方式启动子线程(正常启动)
        if((err = pthread_create(&default_th, &attr, th_fn, (void*)0)) != 0){
            perror("pthread create error");
        }
    
        int res = 0;
        if((err = pthread_join(default_th, (void*)&res)) != 0){
            perror("pthread join error");
        }else{
            printf("default return is %d
    ", (int)res);
        }
        printf("----------------------------------------
    ");
    
        //方式2:设置线程属性为分离状态启动
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        out_state(&attr);
        //以分离状态启动子线程
        if((err = pthread_create(&detach_th, &attr, th_fn, (void*)0))!=0){
            perror("pthread create error");
        }
        
        //注意:分离状态的子线程,调用pthread_join将失败!
        if((err = pthread_join(detach_th, (void*)&res)) != 0){
            //perror("pthread join error");
            fprintf(stderr, "%s
    ", strerror(err));
        }else{
            printf("detach return is %d
    ", (int)res);
        }
        
    
        //销毁线程属性
        pthread_attr_destroy(&attr);
    
        printf("0x%lx finished
    ", pthread_self());
        sleep(1);
       
        return 0;
    }
    /*输出结果
     joinable state          //正常状态启动 
     default return is 5050
     ----------------------------------------
     detached state          //分离状态启动
     Invalid argument        //调用pthread_join失败!
     0xb77976bf finished
     */

    3.3 线程优先级设置

    (1)调度策略和获取最高/最低优先级

    头文件

    #include <pthread.h>

    #include <sched.h>

    函数

    //设置调度策略

    int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy);

    //获取可设置的最高、最低优先级

    int sched_get_priority_max(int policy);

    int sched_get_priority_min(int policy);

    返回值

    成功返回0,否则返回错误编号

    参数

    policy的取值

    ①SCHED_OTHER:分时调度策略,不支持优先级使用。(默认调度策略)

    ②SCHED_FIFO:实时调度策略。一旦占用CPU则一直运行。直到有更高优先级到达或自己放弃

    ③SCHED_RR:实时调度策略,时间片轮转。当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。

    (2)获取和设置优先级

    头文件

    #include <pthread.h>

    #include <sched.h>

    函数

    int pthread_attr_setschedparam(pthread_addr_t* attr, const struct sched_param* param); //设置优先级

    int  pthread_attr_getschedparam(const pthread_attr_t* attr, struct sched_param* param); //获取优先级

    返回值

    成功返回0,否则返回错误编号

    参数

    struct sched_param
    {
        int32_t sched_priority; //所要设定的线程优先级(1-99),数值越大,优先级越高。
    };

    【编程实验】设置线程优先级

    //pthread_priority.c

    #include <pthread.h>
    #include <sched.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    /*改变线程调度策略和优先级*/
    
    //显示线程的调度策略和优先级
    void show_attr(int threadid, int policy, int priority)
    {
        printf("thread%d ", threadid);
        switch(policy)
        {
        case SCHED_OTHER:
            printf("policy = SCHED_OTHER");
            break;
        case SCHED_RR:
            printf("policy = SCHED_RR");
            break;
        case SCHED_FIFO:
            printf("policy = SCHED_FIFO");
            break;
        default:
            printf("policy = UNKNOW");
            break;
        }
        printf(" priority = %d
    ", priority);
    }
    
    void* th_fn(void* arg)
    {
        int id = (int)arg;
    
        int i, j;
        int policy;
        struct sched_param param;
        
        //获取当前线程的线程调度策略和优先级
        pthread_getschedparam(pthread_self(), &policy, &param);
        show_attr(id, policy, param.sched_priority);
    
        for(i=1; i<10;i++){
            for(j=1;j<100000000;j++);
            printf("%d thread%d
    ", i, id);
        }
    
        printf("thread%d exit
    ", id);
        
        return (void*)0;
    }
    
    int main(void)
    {
        pthread_t t1, t2, t3;
        struct sched_param param;
        pthread_attr_t attr1, attr2, attr3;
        
        pthread_attr_init(&attr1); 
        pthread_attr_init(&attr2);
        pthread_attr_init(&attr3);
        
        //线程1按默认的调度策略和优先级:SCHED_OTHER
    
        //线程2的调度策略为SCHED_RR,优先级为21
        param.sched_priority = 21;
        pthread_attr_setschedpolicy(&attr2, SCHED_RR);//调度策略
        pthread_attr_setschedparam(&attr2, &param);   //优先级
        pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED); //不继承父线程的调度策略,
                                                                      //而是由用户自己指定调度策略
    
        //线程3的为SCHED_RR调度,优先级为51
        param.sched_priority = 51; //数值越大,优先级越高!
        pthread_attr_setschedpolicy(&attr3, SCHED_RR);
        pthread_attr_setschedparam(&attr3, &param);
        pthread_attr_setinheritsched(&attr3, PTHREAD_EXPLICIT_SCHED);
    
        //创建3个子线程
        pthread_create(&t1, &attr1, th_fn, (void*)1);
        pthread_create(&t2, &attr2, th_fn, (void*)2);
        pthread_create(&t3, &attr3, th_fn, (void*)3);
       
       //等待子线程结束
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
        pthread_join(t3, NULL);
    
        //销毁线程属性
        pthread_attr_destroy(&attr1);
        pthread_attr_destroy(&attr2);
        pthread_attr_destroy(&attr3);
    
        return 0;
    }
     /* 输出结果
     * thread2 policy = SCHED_RR priority = 11
     * 1 thread2
     * 2 thread2
     * 3 thread2
     * thread1 policy = SCHED_OTHER priority = 0 
     * thread3 policy = SCHED_RR priority = 51  //线程1被线程3抢占
     * 1 thread3
     * 2 thread3
     * 3 thread3
     * 4 thread3
     * 5 thread3
     * 6 thread3
     * 7 thread3
     * 8 thread3
     * 9 thread3
     * thread3 exit
     * 4 thread2
     * 5 thread2
     * 6 thread2
     * 7 thread2
     * 8 thread2
     * 9 thread2
     * thread2 exit
     * 1 thread1
     * 2 thread1
     * 3 thread1
     * 4 thread1
     * 5 thread1
     * 6 thread1
     * 7 thread1
     * 8 thread1
     * 9 thread1
     * thread1 exit
     *从输出结果看,得到如下结论:
     *(1)线程1为普通调度策略(SCHED_OTHER),线程2和线程3为时间片轮转实时调度策略(SCHED_RR)
     *(2)优先级高的线程3并没有最先运行,但获的时间片更多。
     *(3)线程2、3为实时线程,所以最先运行完,线程1为普通线程最后运行结束。
     */
  • 相关阅读:
    [wikioi]最长严格上升子序列
    [leetcode]Pascal's Triangle II
    [leetcode]Remove Duplicates from Sorted Array II
    [leetcode]Remove Duplicates from Sorted List
    STL中set底层实现方式
    有N个大小不等的自然数(1--N),请将它们由小到大排序。要求程序算法:时间复杂度为O(n),空间复杂度为O(1)。
    C#基本语句
    C#程序大打开
    如何知道自己是工作组计算机中的哪个
    weka平台
  • 原文地址:https://www.cnblogs.com/5iedu/p/6545628.html
Copyright © 2011-2022 走看看