主執行緒和子執行緒多種情況小探討
阿新 • • 發佈:2022-12-08
一.背景
今天看了一篇有關volatile在多執行緒中使用的部落格(自己對該部落格的總結:https://i-beta.cnblogs.com/posts/edit;postId=11388620),裡面的例子沒有詳細地進行程式碼實現.自己想要驗證下這個問題,同時練習下多執行緒程式設計的招式,去專門實現了一下.發現真正自己去動手時,頭腦中會湧現出很多的疑問,同時也產生了很多的收穫.
二.程式碼示例
程式碼要實現的功能是每隔一秒對flag_進行判斷,如果flag_被另外的執行緒改為true的話,就會跳出迴圈.
這裡主要是針對主執行緒和子執行緒使用時,嘗試了多種組合,看看都會有怎樣的化學反應.
#include <iostream> #include <windows.h> using namespace std; class Test { private: volatile bool m_bFlag; public: Test() { m_bFlag = false; } void Wait() { while (!m_bFlag) { cout << "I'm Sleeping" << endl; Sleep(1000); } cout << "I'm awake" << endl; } void WakeUp() { m_bFlag = true; } }; DWORD WINAPI ThreadFun2(void *param) { Test *tThread = (Test *)param; tThread->WakeUp(); return 0; } DWORD WINAPI ThreadFun1(void *param) { Test *tThread = (Test *)param; tThread->Wait(); return 0; } /*下面實現一個執行緒隔1s進行等待判斷,並且顯式打印出"I'm Sleeping",另一個執行緒去把它的等待結束的過程.並標註下能否實現該需求.*/ //這種情形會一閃而過,因為主執行緒沒有等待子執行緒的過程,主執行緒結束後進程結束,子執行緒也終止了. //未能實現 int main1() { Test t; //建立子執行緒 HANDLE h = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL); t.WakeUp(); return 0; } //會造成只執行子執行緒,主執行緒不執行的問題.這個時候我就誤以為是主執行緒和子執行緒不能夠同時運行了,其實這裡是主執行緒使用讓著子執行緒. //未能實現 int main2() { Test t; //建立子執行緒 HANDLE h = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL); WaitForSingleObject(h, INFINITE); //INFINITE表示等待子執行緒結束後,才會走下面的邏輯.這裡子執行緒的死迴圈無法打破,會一直阻塞在這裡. t.WakeUp(); return 0; } //這種情況能夠保證子執行緒執行3s,然後把它WakeUp. //能實現 int main3() { Test t; //建立子執行緒 HANDLE h = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL);//主執行緒結束後,子執行緒也隨之結束. Sleep(3000);//此處Sleep讓你能看到子執行緒列印I'm Sleeping //呼叫過WakeUp後,要Sleep一會,不然主執行緒就直接結束了. t.WakeUp(); Sleep(2000); return 0; } //這種只是來演示,主執行緒為死迴圈時,和子執行緒交替執行的情形. //不能實現 int main4() { Test t; //建立子執行緒 HANDLE h = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL);//如果是死迴圈,那麼主執行緒不結束,子執行緒也不會結束. while (true) { Sleep(1000); cout << "主執行緒" << endl; } return 0; } //用兩個子執行緒實現,發現兩個子執行緒之間的生存期是相互獨立的.它們只受主執行緒的影響. //可以實現. int main5() { Test t; HANDLE h[2]; h[0] = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL); Sleep(10);//如果不加這個Sleep,多數情況下會先列印Sleeping,然後列印awake,但是也有情況會直接列印awake. h[1] = CreateThread(NULL, 0, ThreadFun2, &t, 0, NULL); WaitForMultipleObjects(2, h, TRUE, INFINITE); return 0; }
三.收穫
1.主執行緒結束後進程結束,子執行緒也終止了.
2.如果不設定主執行緒去等待子執行緒,兩者是交替執行的.比如main4.
3.兩個子執行緒之間的生存期是相互獨立的