1. 多线程编程的核心价值
在当代软件开发中,多线程技术早已从可选技能变成了必备能力。我处理过太多因为线程管理不当导致的性能瓶颈——那个卡顿的界面、那个响应迟缓的服务端、那个CPU利用率始终上不去的计算程序,问题根源往往都在线程使用上。
Windows平台下,CreateThread这个API就像一把双刃剑。用得好了,程序性能直接起飞;用不好,内存泄漏、死锁崩溃接踵而至。十年前我第一次用CreateThread实现下载器多任务时,就经历过线程句柄忘记关闭导致系统资源耗尽的惨痛教训。
2. CreateThread原理深度解析
2.1 线程创建的底层机制
当调用CreateThread时,Windows内核会在进程地址空间内分配一个线程内核对象(Thread Kernel Object)。这个对象包含线程上下文、优先级、退出码等关键信息,其初始引用计数为2。很多人不知道的是,即便线程函数执行完毕,只要没调用CloseHandle,这个内核对象就会一直存在。
线程栈的分配策略值得特别注意:默认情况下,系统会为每个线程预留1MB的栈空间(可通过/STACK链接器选项修改)。我曾遇到过一个案例,某程序创建了500个线程导致虚拟地址空间耗尽,就是因为不了解这个机制。
2.2 参数传递的陷阱
LPVOID lpParameter这个参数看似简单,实则暗藏杀机。最常见的问题是将局部变量地址传递给线程:
cpp复制void createProblemThread() {
int localVar = 42;
CreateThread(NULL, 0, ThreadFunc, &localVar, 0, NULL);
// 函数返回后localVar内存失效!
}
正确的做法是动态分配内存或用智能指针管理生命周期。我推荐使用std::make_shared配合lambda表达式,这是现代C++最安全的方案:
cpp复制auto data = std::make_shared<MyData>();
CreateThread(NULL, 0, [](LPVOID p) -> DWORD {
auto ptr = static_cast<std::shared_ptr<MyData>*>(p);
