C Pthread优先级:无法获得预期的行为

在这里,我正在尝试创建两个线程,为它们分配优先级/策略并获得预期的行为。

预期的行为:具有最高优先级的线程(在这种情况下为thread1)应始终首先执行。 我看到的是:线程输出混杂在一起,这意味着没有遵循优先级。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sched.h>


void *thread_func1 ();
void *thread_func2 ();

int main (){

    pthread_t thread1,thread2;
    pthread_attr_t attr1,attr2; 

    struct sched_param param1,param2;

    int thread1_prio = 70;
    int thread2_prio = 69;

    int policy1,policy2;

    policy1 = SCHED_RR;
    policy2 = SCHED_RR;

    pthread_attr_init(&attr1);
    pthread_attr_init(&attr2);


    param1.sched_priority = thread1_prio;
    param2.sched_priority = thread2_prio;

    pthread_attr_setschedparam(&attr1,&param1);
    pthread_attr_setschedparam(&attr2,&param2);

    pthread_attr_setschedpolicy(&attr1,policy1);
    pthread_attr_setschedpolicy(&attr2,policy2);   

    pthread_attr_getschedparam(&attr1,&param1);
    pthread_attr_getschedparam(&attr2,&param2);

    pthread_attr_getschedpolicy(&attr1,&policy1);
    pthread_attr_getschedpolicy(&attr2,&policy2);  

    pthread_create(&thread1,&attr1,thread_func1,NULL);
    pthread_create(&thread2,&attr2,thread_func2,NULL);
    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);


    return 0;
}

void *thread_func1 (void *var){

    for (int i = 0; i<5; i++){
        printf("Thread: 1\n");
    }

    return 0;
}

void *thread_func2 (void *var){

    for (int i=0; i<5; i++){
        printf("Thread: 2\n");
    }
    return 0;
}
  • 我也尝试使用pthread_setschedprio,但仍然无法获得预期的结果。
  • root的身份执行程序

在发布此问题之前,我确实尝试关注许多帖子/示例,但最终变得更加困惑。任何帮助表示赞赏。

编辑:这不是一个真正的问题吗?我的意思是,如果发布此消息很愚蠢,请纠正我,并应得下票,因为其中一些人已经对该帖子投了反对票?

yangzhulian 回答:C Pthread优先级:无法获得预期的行为

  

预期的行为:具有最高优先级的线程(在这种情况下为thread1)应始终首先执行。

通常,Linux不能那样工作。基础设计围绕时间共享展开,其中任务的优先级会影响任务获得的CPU时间的百分比,并且对延迟或抢占没有影响。根本不打算像您想要的那样执行“可以运行的最高优先级任务确实可以运行(并且优先于低优先级任务)”。

此外:

  • pthread优先级几乎完全被破坏并且不受任何支持(除了实时调度策略,常规软件不应该使用该策略,如果您对实时性有严格要求,则可能不应该使用它) )。

  • nice()也被破坏了,因为它影响单个线程,而不是像预期的那样属于整个进程的所有线程。这种破坏性意味着您可以勇敢地使用nice()而不是pthread优先级。

  • “优先级” /很好的限制的行为(或者至少是,我没有检查它最近是否被修复)也被破坏了;因为无论限制是多少,您都只能降低任务的优先级,而不能将任务的优先级提高到极限。这完全破坏了几种常见的设计(例如,“工作线程从队列中获取工作,然后调整其优先级以适合该工作”,“线程预先生成对象以供将来使用,然后将其放入池中,并将其优先级调整为满足需求(取决于池的满/空)”。

最终结果是(没有极端的麻烦-例如,内核破碎的混乱之上的用户空间线程层),您实际上可以通过滥用“ SCHED_RR”来模仿微不足道的“ 2优先级”系统(加nice()表示微不足道/较小的调整),将其作为高/中优先级,将“ SCHED_IDLE”作为低优先级。

主要是;最好忘记编写正确使用线程优先级的软件(这太难了,不便于移植,只能提供应有的部分好处)。当然,这也是潜在的问题(因为大多数软件不使用线程优先级,因此内核开发人员并不十分在意理解调度程序应如何工作并且不修复线程优先级,因此大多数软件都不使用线程优先事项-这是一个自我永存的白痴反馈循环,至今已持续了30年)。

,

我装饰了您的程序以检查错误,并显示以下行:

pthread_attr_setschedparam(&attr1,&param1);

始终以EINVAL失败,是否为root。快速查看手册,发现在此之前,您必须:

pthread_attr_setinheritsched(&attr1,PTHREAD_EXPLICIT_SCHED);

那还不能完全解决,更模糊的是您必须在优先级之前设置策略,因此顺序是:setinheritsched,setchedpolicy,setschedparam。

任何人都猜测您的特定posix-OS是否对调度参数有任何有用的作用,但这至少给了它很大的战斗机会。

一些注意事项:

  1. 要正确观察此情况,您需要将线程仿射到单个cpu。
  2. 您要么需要使main()的优先级高于任一线程,要么强制线程从障碍处开始,以便可以同时释放它们。否则,您的第一个线程可能会在第二个线程开始之前运行完毕。
  3. Posix线程属性是一团糟,您真的想测试它们是否失败。我通常将它们包装在类似断言的宏中。

通过这些更正和增强,在我的ubuntu 16上,您的程序按预期运行。

本文链接:https://www.f2er.com/3138512.html

大家都在问