面试题答案
一键面试配置思路
- 线程数量:
- 在Linux平台,可通过
sysconf(_SC_NPROCESSORS_ONLN)
获取CPU核心数,根据任务类型(CPU密集型或I/O密集型)来决定线程数量。对于CPU密集型任务,线程数可接近或等于CPU核心数;对于I/O密集型任务,可适当增加线程数,比如2倍CPU核心数。 - 在Windows平台,使用
GetSystemTimes()
函数获取CPU核心数,同样依据任务类型配置线程数量。 - 在macOS平台,可使用
sysctl
函数获取CPU核心数,类似地根据任务特性配置线程数。
- 在Linux平台,可通过
- 优先级:
- 在Linux平台,可使用
pthread_setschedparam
函数设置线程优先级,根据任务的重要性分配不同优先级。例如,关键任务设置较高优先级,后台任务设置较低优先级。 - 在Windows平台,使用
SetThreadPriority
函数设置线程优先级,同样按任务重要性划分优先级。 - 在macOS平台,使用
pthread_setqualityofservice_np
函数设置线程优先级,依据任务重要程度分配优先级。
- 在Linux平台,可使用
- 栈大小:
- 在Linux平台,可在
std::thread::Builder
中通过stack_size
函数设置栈大小,一般默认栈大小可能足够,但对于某些需要大量局部变量或递归调用的任务,可能需要增加栈大小。 - 在Windows平台,
std::thread::Builder
同样可使用stack_size
函数设置栈大小,根据任务需求调整。 - 在macOS平台,类似地使用
std::thread::Builder
的stack_size
函数设置栈大小,依据具体任务情况确定合适的栈大小。
- 在Linux平台,可在
核心代码片段
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <functional>
#include <atomic>
std::mutex mtx;
std::condition_variable cv;
std::queue<std::function<void()>> task_queue;
std::atomic<bool> stop(false);
std::vector<std::thread> threads;
void worker_thread() {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return!task_queue.empty() || stop; });
if (stop && task_queue.empty()) break;
task = std::move(task_queue.front());
task_queue.pop();
}
task();
}
}
void create_thread_pool(int num_threads) {
for (int i = 0; i < num_threads; ++i) {
threads.emplace_back(worker_thread);
}
}
void add_task(std::function<void()> task) {
{
std::unique_lock<std::mutex> lock(mtx);
task_queue.push(std::move(task));
}
cv.notify_one();
}
void stop_thread_pool() {
{
std::unique_lock<std::mutex> lock(mtx);
stop = true;
}
cv.notify_all();
for (auto& thread : threads) {
thread.join();
}
}
在主函数中可以这样调用:
int main() {
// 获取CPU核心数
int num_threads = std::thread::hardware_concurrency();
create_thread_pool(num_threads);
// 添加任务
add_task([]{ std::cout << "Task 1 executed." << std::endl; });
add_task([]{ std::cout << "Task 2 executed." << std::endl; });
// 停止线程池
stop_thread_pool();
return 0;
}
不同平台下可能面临的挑战及解决方案
- Linux平台:
- 挑战:不同Linux发行版对线程调度策略的实现可能略有不同,一些系统可能对实时调度策略有严格限制。
- 解决方案:在设置线程优先级和调度策略时,仔细查阅系统文档,使用符合POSIX标准的函数,并进行充分测试,确保在不同发行版上都能正常工作。
- Windows平台:
- 挑战:Windows的线程调度模型与Linux和macOS不同,设置线程优先级时需要注意不同优先级级别对系统资源的影响,过高优先级可能导致其他线程饥饿。
- 解决方案:在设置优先级时,根据任务的实际需求,合理选择优先级级别,避免设置过高优先级。同时,通过性能测试工具监控系统资源使用情况。
- macOS平台:
- 挑战:macOS的线程调度与BSD系统相关,一些函数的使用可能与Linux和Windows有所差异,例如设置线程优先级的函数接口不同。
- 解决方案:深入了解macOS的线程调度机制,使用macOS特定的函数接口,如
pthread_setqualityofservice_np
,并参考苹果官方文档进行正确配置和使用。