Linux系统编程之线程优先级

server/2025/1/14 5:38:56/

概述

        在Linux系统中,线程优先级是影响多线程应用程序性能和响应速度的关键因素之一。通过合理设置线程优先级,可以确保关键任务得到及时处理,同时避免低优先级任务过度占用系统资源。

        线程优先级是指操作系统根据一定的规则分配给每个线程的一个数值,用于决定该线程获得CPU时间的顺序和频率。一般来说,优先级越高,线程越有可能被调度执行。相反,优先级较低的线程则需要等待高优先级线程完成之后才能获得CPU时间。然而,这并不意味着低优先级线程永远不会被执行,而是它们的执行机会相对较少。

优先级范围

        Linux支持多种线程调度策略,在每种策略下,线程都有其特定的优先级范围。下面,我们将介绍几种常见的调度策略。

        1、先入先出(SCHED_FIFO)。一种实时调度策略,适用于对延迟敏感的应用程序。一旦线程开始运行,它会一直占用CPU直到主动放弃或完成任务,不受其他同优先级线程的影响。其优先级范围为1到99,数字越大表示优先级越高。

        2、轮转调度(SCHED_RR)。类似于SCHED_FIFO,但为每个线程分配了一个固定的时间片。当一个线程用完其时间片后,即使没有完成工作也会被暂停,让位于下一个同优先级的线程。其优先级范围同样为1到99,数字越大表示优先级越高。

        3、完全公平调度器(SCHED_OTHER)。Linux默认的非实时调度策略,适用于大多数普通应用。基于虚拟运行时间来衡量每个线程应当获得多少CPU时间,保证所有线程都能公平地获得CPU资源。其优先级范围为-20到19,可通过nice值调整,默认值为0。nice值越小,优先级越高;nice值越大,优先级越低。

        4、批处理调度和低优先级调度(SCHED_BATCH和SCHED_IDLE)。这两个调度策略主要用于后台批处理作业或低优先级服务,其优先级范围通常不需要显式设置。

设置线程优先级

        pthread_setschedparam函数用于设置线程调度参数,允许我们指定线程的调度策略和优先级。其函数原型如下。

int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);

        各个参数和返回值的含义如下。

        thread:表示要修改调度参数的线程,可通过pthread_self函数获取当前线程的ID,也可使用其他方式获取特定线程的ID。

        policy:指定线程的调度策略,可取值包括上面介绍的SCHED_FIFO、SCHED_RR、SCHED_OTHER、SCHED_BATCH、SCHED_IDLE。

        param:指向struct sched_param类型的指针,包含线程的调度参数。其主要成员是sched_priority,它定义了线程的优先级。如前所述,对于不同的调度策略,优先级的有效范围也不同。

        返回值:成功时返回0,失败时可通过errno获取具体的错误代码。常见的错误代码为:EINVAL(调度策略无效或优先级超出允许范围)、EPERM(没有足够的权限)、ESRCH(没有找到对应的线程)。

        在下面的示例代码中,我们创建了两个线程:一个由主线程设置优先级,另一个在其自身的线程函数内设置优先级。主线程创建external_priority_thread线程后,立即设置其为实时优先级30,并执行简单的工作循环。internal_priority_thread线程启动后,自行将其优先级提升至50,并执行类似的工作循环。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>// 在线程外部(主线程中)设置优先级
void* external_priority_thread(void* arg)
{for (int i = 0; i < 5; ++i){printf("External-priority thread working... %d\n", i);sleep(1);}return NULL;
}// 在线程内部设置优先级
void* internal_priority_thread(void* arg)
{// 获取当前线程的调度策略和优先级int policy = 0;struct sched_param param;pthread_getschedparam(pthread_self(), &policy, &param);printf("Internal-priority thread initial priority: %d\n", param.sched_priority);// 尝试设置新的高优先级param.sched_priority = 50;pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);for (int i = 0; i < 5; ++i){printf("Internal-priority thread working... %d\n", i);sleep(1);}return NULL;
}int main()
{// 创建线程,在线程外部(主线程中)设置优先级pthread_t ext_prio_thread;struct sched_param param = { .sched_priority = 30 };pthread_create(&ext_prio_thread, NULL, external_priority_thread, NULL);pthread_setschedparam(ext_prio_thread, SCHED_FIFO, &param);// 创建线程,在线程内部设置优先级pthread_t int_prio_thread;pthread_create(&int_prio_thread, NULL, internal_priority_thread, NULL);// 等待两个线程完成pthread_join(ext_prio_thread, NULL);pthread_join(int_prio_thread, NULL);printf("Both threads have completed\n");return 0;
}

注意事项

        1、确保设置的优先级在所选调度策略的有效范围内,超出范围可能会导致EINVAL错误。

        2、对于实时调度策略(比如:SCHED_FIFO或SCHED_RR),可能需要超级用户权限才能成功设置线程优先级。普通用户创建的线程默认采用SCHED_OTHER策略,并且其优先级受到限制。

        3、高优先级线程会抢占低优先级线程的CPU时间,可能导致系统饥饿现象。因此,在设定优先级时,应当谨慎权衡各个线程的重要性。

        4、在某些情况下,可以根据应用程序的状态来动态调整线程优先级。比如:当检测到系统负载过高时,适当降低一些非关键线程的优先级,以释放更多资源给更重要的任务。


http://www.ppmy.cn/server/158197.html

相关文章

机器学习与人工智能的关系

机器学习与人工智能的关系 一、人工智能二、机器学习2.1 机器学习与人工智能的关系2.2 机器学习的本质 三、其他玩艺 曾几何时&#xff0c;人工智能还是个科幻名词&#xff0c;仿佛只属于未来世界。如今&#xff0c;它已经渗透到了我们生活的方方面面&#xff0c;成为顶流。我们…

使用vue3、vite打包项目中组件库中的某一个组件,并将其推送至npm上

最近公司人手不够&#xff0c;老板将一个项目交给外包团队进行协助开发&#xff0c;老板又不希望外包团队可以看某些业务上的组件代码&#xff0c;让我解决这个问题&#xff1b;查找了一下解决方案&#xff0c;可以将组件类似于项目打包一样&#xff0c;将其打包成一个依赖组件…

Kubeflow:云原生机器学习工作流自动化开源框架详解

Kubeflow 是一个开源的 机器学习&#xff08;ML&#xff09;工作流自动化平台&#xff0c;旨在将机器学习工作流部署到 Kubernetes 之上&#xff0c;实现从实验到生产的一站式解决方案。它提供了针对容器化机器学习任务的工具链&#xff0c;能够自动化地管理、部署和监控模型的…

springboot整合gateway

1. 添加依赖 首先&#xff0c;在你的pom.xml文件中添加Spring Cloud Gateway的依赖&#xff1a; <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency> 如果…

Vue.js组件开发-如何使用day.js、luxon或date-fns处理日期时间

在Vue.js组件开发中&#xff0c;使用day.js、luxon或date-fns等现代日期处理库可以大大简化日期和时间的操作。 示例&#xff1a; 1.使用 day.js day.js 是一个轻量级的日期处理库&#xff0c;它的API设计与 moment.js 非常相似&#xff0c;但体积更小。 ‌安装‌ npm ins…

Http协议封装

Myhttp封装http协议 源代码 #include <iostream> #include <cstring> #include <string> #include <thread> #include <atomic> #include <fstream> // 添加文件操作头文件#ifdef _WIN32 #include <winsock2.h> #include <ws2t…

8 事件等待

临界区&自旋锁 这两个章节在”多核同步“篇已经学习过了,需要了解的可以自行查看对应章节。 线程等待与唤醒 我们在之前的课程里面了解了如何自己实现临界区以及什么是Windows自旋锁,这两种同步方案在线程无法进入临界区时都会让当前线程进入等待状态。 一种是通过Sl…

MySQL程序之:简要概述

MySQL安装中有许多不同的程序。本节简要概述了它们。后面的部分提供了每个程序的更详细描述&#xff0c;但NDB集群程序除外。每个程序的描述表明了它的调用语法和它支持的选项。&#xff0c;“NDB集群程序”&#xff0c;描述了特定于NDB集群的程序。 大多数MySQL发行版包括所有…