在多核处理器普及的当下,多线程程序的性能优化除了算法层面的调整,线程调度相关的配置也至关重要。线程优先级决定了线程获取CPU执行时间的先后,而CPU亲和性则可以将指定线程绑定到特定的CPU核心上运行,减少线程迁移带来的缓存失效问题,两者结合能大幅提升程序运行效率。

线程优先级设置
Linux系统下的实现
Linux系统中可以通过pthread库提供的接口设置线程优先级,优先级数值越小表示优先级越低,实时优先级范围通常为1到99,普通线程优先级范围可以通过相关接口查询。
#include <pthread.h>
#include <iostream>
#include <cstring>
int main() {
pthread_t thread;
pthread_attr_t attr;
struct sched_param param;
// 初始化线程属性
pthread_attr_init(&attr);
// 设置线程为分离状态,可选配置
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 获取当前调度策略和优先级范围
int policy;
pthread_attr_getschedpolicy(&attr, &policy);
int min_priority = sched_get_priority_min(policy);
int max_priority = sched_get_priority_max(policy);
std::cout << "优先级范围: " << min_priority << " 到 " << max_priority << std::endl;
// 设置线程优先级为范围内的中间值
param.sched_priority = (min_priority + max_priority) / 2;
pthread_attr_setschedparam(&attr, ¶m);
// 创建线程时应用属性
int ret = pthread_create(&thread, &attr, [](void*) -> void* {
std::cout << "子线程运行中" << std::endl;
return nullptr;
}, nullptr);
if (ret != 0) {
std::cerr << "线程创建失败: " << strerror(ret) << std::endl;
}
// 销毁线程属性
pthread_attr_destroy(&attr);
// 主线程等待一段时间,避免子线程未执行就退出
sleep(1);
return 0;
}
Windows系统下的实现
Windows系统通过Windows API提供的SetThreadPriority函数设置线程优先级,优先级分为多个等级,从低到高包括THREAD_PRIORITY_LOWEST、THREAD_PRIORITY_BELOW_NORMAL、THREAD_PRIORITY_NORMAL等。
#include <windows.h>
#include <iostream>
DWORD WINAPI ThreadFunc(LPVOID lpParam) {
std::cout << "Windows子线程运行中" << std::endl;
return 0;
}
int main() {
HANDLE hThread = CreateThread(
NULL, // 默认安全属性
0, // 默认栈大小
ThreadFunc, // 线程函数
NULL, // 线程参数
0, // 默认创建标志
NULL // 不需要线程ID
);
if (hThread == NULL) {
std::cerr << "线程创建失败" << std::endl;
return 1;
}
// 设置线程优先级为高于普通级别
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
// 等待线程执行完成
WaitForSingleObject(hThread, INFINITE);
// 关闭线程句柄
CloseHandle(hThread);
return 0;
}
CPU亲和性设置
Linux系统下的实现
Linux系统通过cpu_set_t结构体和相关操作函数设置CPU亲和性,可以将线程绑定到指定的一个或多个CPU核心上运行。
#include <pthread.h>
#include <iostream>
#include <unistd.h>
int main() {
pthread_t thread;
cpu_set_t cpu_set;
// 创建线程
pthread_create(&thread, nullptr, [](void*) -> void* {
// 线程内也可以自行设置亲和性
cpu_set_t inner_set;
CPU_ZERO(&inner_set);
// 绑定到CPU核心0
CPU_SET(0, &inner_set);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &inner_set);
std::cout << "子线程绑定到CPU核心0运行" << std::endl;
return nullptr;
}, nullptr);
// 主线程绑定到CPU核心1
CPU_ZERO(&cpu_set);
CPU_SET(1, &cpu_set);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu_set);
std::cout << "主线程绑定到CPU核心1运行" << std::endl;
pthread_join(thread, nullptr);
return 0;
}
Windows系统下的实现
Windows系统通过SetThreadAffinityMask函数设置线程的CPU亲和性,参数是一个位掩码,每一位对应一个CPU核心,置1表示允许线程在该核心上运行。
#include <windows.h>
#include <iostream>
DWORD WINAPI ThreadFunc(LPVOID lpParam) {
std::cout << "Windows子线程绑定到指定CPU核心运行" << std::endl;
return 0;
}
int main() {
HANDLE hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
if (hThread == NULL) {
std::cerr << "线程创建失败" << std::endl;
return 1;
}
// 绑定到CPU核心0,位掩码为1即第0位为1
DWORD_PTR affinity_mask = 1;
SetThreadAffinityMask(hThread, affinity_mask);
// 主线程绑定到CPU核心1,位掩码为2即第1位为1
SetThreadAffinityMask(GetCurrentThread(), 2);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}
注意事项
- 设置线程优先级时需要确保进程有足够的权限,尤其是Linux系统下设置实时优先级通常需要root权限。
- CPU亲和性设置不宜过度,如果绑定核心过多可能导致其他线程无法获取执行资源,反而降低整体性能。
- 不同操作系统下的接口互不兼容,跨平台程序需要做好条件编译适配。
- 线程优先级和CPU亲和性设置需要结合实际业务场景,CPU密集型线程适合绑定固定核心,IO密集型线程则不需要过度限制。