在 Windows 平台下使用 CreateThread 創建子線程時,許多初學者會遇到一個經典問題:子線程中的輸出語句(如 cout << "進入線程" << endl;)並未執行,程序直接退出。以下代碼示例展示了這一現象:
using namespace std;
DWORD WINAPI Thread_accept(PVOID lParam) {
cout << "進入線程" << endl;
return 0;
}
int main() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
HANDLE Thread;
Thread = CreateThread(NULL, 0, Thread_accept, NULL, 0, NULL);
return 0;
}
主線程過早退出 是導致子線程未執行的根本原因。在上述代碼中,main() 函數在調用 CreateThread 後立即執行 return 0;,導致進程終止。此時子線程可能尚未獲得 CPU 時間片,或者剛開始初始化,隨著進程結束而被強制銷毀,因此輸出語句無法執行。
為了確保子線程有機會執行,主線程必須等待子線程結束。常見的同步機制包括:
WaitForSingleObject 等待線程句柄WaitForSingleObject(Thread, INFINITE);
CloseHandle(Thread);
這是最標準的做法,主線程阻塞直到子線程運行完畢。
volatile BOOL g_bThreadFinished = FALSE;
DWORD WINAPI Thread_accept(PVOID lParam) {
cout << "進入線程" << endl;
g_bThreadFinished = TRUE;
return 0;
}
int main() {
// ... 創建線程代碼 ...
while (!g_bThreadFinished) {
Sleep(10); // 避免佔用過多 CPU
}
return 0;
}
適用於簡單場景,但需注意 volatile 關鍵字防止編譯器優化。
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD WINAPI Thread_accept(PVOID lParam) {
cout << "進入線程" << endl;
SetEvent(hEvent);
return 0;
}
int main() {
// ... 創建線程代碼 ...
WaitForSingleObject(hEvent, INFINITE);
CloseHandle(hEvent);
return 0;
}
事件對象提供更靈活的同步控制,適合複雜場景。
CloseHandle 釋放線程句柄,避免資源洩漏。std::thread 和 join(),代碼更具可移植性和安全性。子線程不執行輸出的本質是主線程過早退出導致進程終止。通過引入同步機制(等待線程句柄、事件、條件變量等),可以確保子線程獲得完整的執行機會。掌握線程同步是多線程編程的基礎,也是避免此類問題的關鍵。