在 Windows 平台上进行多线程编程时,CreateThread
和 _beginthreadex
是两种我们常用的创建线程的方法。它们都用于启动新的执行线程,但它们之间存在一些关键的区别,特别是在与 C 运行时库(CRT)的交互方面。
CreateThread
- 低级 API:
CreateThread
是 Windows API 提供的一个函数,用于创建新的线程。它是操作系统级别的函数,不涉及 C 运行时库。 - CRT 初始化问题:直接使用
CreateThread
启动的线程不会正确初始化 C 运行时库。这意味着如果你的线程函数中使用了任何 CRT 函数(如malloc
,free
,printf
等),可能会导致不可预测的行为或内存泄漏。 - 简单性:由于
CreateThread
是操作系统级别的函数,它提供了更直接和简单的线程创建方式,但缺乏与 CRT 的集成。
_beginthreadex
- CRT 友好:
_beginthreadex
是 C 运行时库提供的一个函数,用于创建新的线程。它内部调用了CreateThread
,但在此之前会执行一些必要的 CRT 初始化工作。 - 正确初始化:使用
_beginthreadex
创建的线程会正确初始化 C 运行时库,确保所有 CRT 函数在多线程环境中的安全使用。 - 推荐使用:对于需要使用 CRT 函数的应用程序,推荐使用
_beginthreadex
而不是CreateThread
,以避免潜在的 CRT 相关问题。
接下来是 DEMO
使用 CreateThread
#include <windows.h>
#include <stdio.h>DWORD WINAPI ThreadFunc(LPVOID lpParam) {printf("Thread is running.\n");return 0;
}int main() {HANDLE hThread = CreateThread(NULL, // 默认安全属性0, // 默认堆栈大小ThreadFunc, // 线程函数NULL, // 线程参数0, // 默认创建标志NULL); // 不需要线程标识符if (hThread == NULL) {printf("CreateThread failed (%d)\n", GetLastError());return 1;}// 等待线程结束WaitForSingleObject(hThread, INFINITE);// 关闭线程句柄CloseHandle(hThread);return 0;
}
使用 _beginthreadex
#include <windows.h>
#include <process.h> // For _beginthreadex
#include <stdio.h>unsigned __stdcall ThreadFunc(void* lpParam) {printf("Thread is running.\n");return 0;
}int main() {HANDLE hThread = (HANDLE)_beginthreadex(NULL, // 默认安全属性0, // 默认堆栈大小ThreadFunc, // 线程函数NULL, // 线程参数0, // 默认创建标志NULL); // 不需要线程标识符if (hThread == NULL) {printf("_beginthreadex failed\n");return 1;}// 等待线程结束WaitForSingleObject(hThread, INFINITE);// 关闭线程句柄CloseHandle(hThread);return 0;
}
总结下以上的内容
- 兼容性:如果我们应用程序大量使用 CRT 函数,建议使用
_beginthreadex
来创建线程,以确保 CRT 的正确初始化和线程安全。 - 性能:对于不涉及 CRT 函数的简单线程,
CreateThread
可能稍微快一些,因为它绕过了 CRT 相关的初始化。 - 推荐实践:为了代码的安全性和可维护性,推荐使用
_beginthreadex
或 C++11 及以后的std::thread
,它们提供了更好的线程管理和 CRT 支持。