zoukankan      html  css  js  c++  java
  • 一个线程调度策略的例子

    创建线程:
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine)(void*), void *arg);

    接下来要说的是:创建线程后,设置线程优先级的问题。

    获取/设置当前线程使用的调度策略:
    函数: int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
    int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); //主要使用sched_param.__sched_priority
    成功返回0,否则返回-1
    policy一般为:SCHED_FIFO, SCHED_RR 和 SCHED_OTHER。其定义出处见sched.h
    /* Scheduling algorithms. */
    #define SCHED_OTHER 0
    #define SCHED_FIFO 1
    #define SCHED_RR 2
    #ifdef __USE_GNU
    # define SCHED_BATCH 3
    # define SCHED_IDLE 5

    系统创建线程时,默认的线程是SCHED_OTHER。
    (1)注意:有时候你会发现获取调度策略返回-1,这种现象跟编译方式有关,请在编译选项上加上-lpthread

    获取某一种调试策略下优先级极值:即获得线程可以设置的最高和最低优先级
    int sched_get_priority_max(int policy);
    int sched_get_priority_min(int policy);
    说明:
    SCHED_OTHER是不支持优先级使用的,
    而SCHED_FIFO和SCHED_RR支持优先级的使用,他们分别为1和99,数值越大优先级越高。
    三种策略下的极值如下:
    SCHED_OTHER: (0-0)
    SCHED_FIFO: (1-99)
    SCHED_RR: (1-99)

    结论:
    如果程序控制线程的优先级,一般是用pthread_attr_getschedpolicy来获取系统使用的调度策略,
    如果是SCHED_OTHER的话,表明当前策略不支持线程优先级的使用,否则可以。当然所设定的优先级范围必须在最大和最小值之间。
    我们可以通过sched_get_priority_max和sched_get_priority_min来获取。
    理论上,可以通过int pthread_attr_setschedpolicy(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);
    其中struct sched_param中的__sched_priority用来设定线程的优先级

    (2)int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);
    int pthread_attr_setschedparam(pthread_attr_t *restrict attr, const struct sched_param *restrict param);
    前者是修改现在正在执行中的线程,具体地说,就是在pthread_create之后才能使用。
    后者是修改将要创建的线程的参数,在pthread_create就要使用了。


    概念:策略优先级:
    函数:int pthread_getschedparam (pthread_t thread, int policy, struct sched_param *param)
    举例,在线程内部编码如下:
    int policy = 0;
    struct sched_param param;
    pthread_getschedparam(pthread_self(),&policy, &param);

    例子:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    void *Thread1(void *arg)
    {
            sleep(1);
            int policy;
            struct sched_param param;
            pthread_getschedparam(pthread_self(), &policy, &param);
            printf("Thread1:policy(%d), PRI(%d)
    ", policy, param.__sched_priority);
    
            for(int i=1;i<10;i++)
            {
                    for(int j=1;j<5000000;j++)
                    {
                    }
                    printf("thread 1
    ");
            }
            printf("Pthread 1 exit
    ");
    }
    
    void *Thread2(void *arg)
    {
            sleep(1);
            int policy;
            struct sched_param param;
            pthread_getschedparam(pthread_self(), &policy, &param);
            printf("Thread2:policy(%d), PRI(%d)
    ", policy, param.__sched_priority);
    
            for(int i=1;i<10;i++)
            {
                    for(int j=1;j<5000000;j++)
                    {
    
                    }
                    printf("thread 2
    ");
            }
            printf("Pthread 2 exit
    ");
    }
    
    void *Thread3(void *arg)
    {
            sleep(1);
            int policy;
            struct sched_param param;
            pthread_getschedparam(pthread_self(),&policy,&param);
            printf("Thread3:policy(%d), PRI(%d)
    ", policy, param.__sched_priority);
    
            for(int i=1;i<10;i++)
            {
                    for(int j=1;j<5000000;j++)
                    {
                    }
                    printf("thread 3
    ");
            }
            printf("Pthread 3 exit
    ");
    }
    
    
    int main()
    {
            int i;
            i = getuid();
            if(i==0)
                    printf("The current user is root
    ");
            else
                    printf("The current user is not root
    ");
    
            pthread_t tid1,tid2,tid3;
            struct sched_param param;
    
            pthread_attr_t attr3,attr2,attr1;
    
            //thread attr init
            pthread_attr_init(&attr1);
            pthread_attr_init(&attr2);
    
            //thread attr setting
            param.sched_priority = 51;
            pthread_attr_setschedpolicy(&attr1,SCHED_RR);
            pthread_attr_setschedparam(&attr1,&param);
            pthread_attr_setinheritsched(&attr1,PTHREAD_EXPLICIT_SCHED);//要使优先级其作用必须要有这句话
    
            param.sched_priority = 21;
            pthread_attr_setschedpolicy(&attr2,SCHED_RR);
            pthread_attr_setschedparam(&attr2,&param);
            pthread_attr_setinheritsched(&attr2,PTHREAD_EXPLICIT_SCHED);
    
            pthread_attr_init(&attr3);
    
            //thread create
            pthread_create(&tid3,&attr3, Thread3,NULL);
            pthread_create(&tid2,&attr2,Thread2,NULL);
            pthread_create(&tid1,&attr1,Thread1,NULL);
    
            //thread wait
            pthread_join(tid3,NULL);
            pthread_join(tid2,NULL);
            pthread_join(tid1,NULL);
    
            //thread desory attr
            pthread_attr_destroy(&attr1);
            pthread_attr_destroy(&attr2);
    
            return 0;
    }

    运行结果:g++ 2-sched.cpp -lpthread

    [root@localhost thread]# ./a.out 
    The current user is root
    Thread1:policy(2), PRI(51)
    Thread2:policy(2), PRI(21)
    Thread3:policy(0), PRI(0
    thread 2
    thread 1
    thread 3
    thread 1
    thread 2
    thread 3
    thread 1
    thread 2
    thread 3
    thread 1
    thread 2
    thread 3
    thread 1
    thread 2
    thread 3
    thread 1
    thread 2
    thread 3
    thread 1
    thread 2
    thread 3
    thread 1
    thread 2
    thread 3
    thread 1
    Pthread 1 exit
    thread 2
    Pthread 2 exit
    thread 3
    Pthread 3 exit

    结论:

    这 里我们可以看到,由于线程3的调度策略是SCHED_OTHER,而线程2的调度策略是SCHED_RR,所以,在Thread3中,线程3被线程1,线 程2给抢占了。由于线程1的优先级大于线程2的优先级,所以,在线程1以先于线程2运行,不过,这里线程2有一部分代码还是先于线程1运行了。
    我原以为,只要线程的优先级高,就会一定先运行,其实,这样的理解是片面的,特别是在SMP的PC机上更会增加其不确定性。
    其实,普通进程的调度,是CPU根据进程优先级算出时间片,这样并不能一定保证高优先级的进程一定先运行,只不过和优先级低的进程相比,通常优先级较高的 进程获得的CPU时间片会更长而已。其实,如果要想保证一个线程运行完在运行另一个线程的话,就要使用多线程的同步技术,信号量,条件变量等方法。而不是绝对依靠优先级的高低,来保证。
    不过,从运行的结果上,我们可以看到,调度策略为SCHED_RR的线程1,线程2确实抢占了调度策略为SCHED_OTHER的线程3。这个是可以理解的,由于SCHER_RR是实时调度策略。
    只有在下述事件之一发生时,实时进程才会被另外一个进程取代。
    (1) 进程被另外一个具有更高实时优先级的实时进程抢占。
    (2) 进程执行了阻塞操作并进入睡眠
    (3)进程停止(处于TASK_STOPPED 或TASK_TRACED状态)或被杀死。
    (4)进程通过调用系统调用sched_yield(),自愿放弃CPU 。
    (5)进程基于时间片轮转的实时进程(SCHED_RR),而且用完了它的时间片。

       基于时间片轮转的实时进程是,不是真正的改变进程的优先级,而是改变进程的基本时间片的长度。所以基于时间片轮转的进程调度,并不能保证高优先级的进程先运行。

  • 相关阅读:
    css相关
    文章管理列表
    高性能MySQL基础篇
    mysql
    node.js开发实战
    React Hooks
    client-*,scroll-*,offset-*的区别
    将create-react-app从javascript迁移到typescript
    为Github项目添加Travis持续集成服务
    cookie储存
  • 原文地址:https://www.cnblogs.com/jacklikedogs/p/4030072.html
Copyright © 2011-2022 走看看