<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ``` // test01CreateThreadConApp210601.cpp : 此文件包含 "main" 函數。程序執行將在此處開始并結束。// #include <iostream> #include <windows.h> using namespace std; HANDLE hMutex = NULL;//互斥量 int inSub = 0; int inParent = 0; //線程函數 DWORD WINAPI sonFun01(LPVOID lpParamter) { for (int i = 0; i < 10; i++) { //請求一個互斥量鎖 WaitForSingleObject(hMutex, INFINITE); ++inSub; cout << "A Thread Fun Display" << inSub<<")s "<< endl; Sleep(100); //釋放互斥量鎖 ReleaseMutex(hMutex); } return 0L;//表示返回的是long型的0 }// int main() { //創建一個子線程 HANDLE hThread = CreateThread(NULL, 0, sonFun01, NULL, 0, NULL); hMutex = CreateMutex(NULL, FALSE, L"screen"); //關閉線程 CloseHandle(hThread); //主線程的執行路徑 Sleep(500); //parent線程先退后,讓子線程先執行 for (int i = 0; i < 10; i++) { //請求獲得一個互斥量鎖 WaitForSingleObject(hMutex, INFINITE); ++inParent; cout << "Main Thread Display:" <<inParent<<"]P "<< endl; Sleep(100); //釋放互斥量鎖 ReleaseMutex(hMutex); } return 0; }//main ``` # [Win32(CreateThread) C++多線程編程(入門實例)](https://www.cnblogs.com/codingmengmeng/p/5913068.html)   多線程在編程中有相當重要的地位,我們在實際開發時或者找工作面試時總能遇到多線程的問題,對多線程的理解程度從一個側面反映了程序員的編程水平。   其實C++語言本身并沒有提供多線程機制(當然目前C++ 11新特性中,已經可以使用std::thread來創建線程了,因為還沒有系統地了解過,所以這里不提了。),但Windows系統為我們提供了相關API,我們可以使用他們來進行多線程編程。 創建線程的API函數 [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") ~~~ HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD:線程安全相關的屬性,常置為NULL SIZE_T dwStackSize,//initialstacksize:新線程的初始化棧的大小,可設置為0 LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction:被線程執行的回調函數,也稱為線程函數 LPVOID lpParameter,//threadargument:傳入線程函數的參數,不需傳遞參數時為NULL DWORD dwCreationFlags,//creationoption:控制線程創建的標志 LPDWORD lpThreadId//threadidentifier:傳出參數,用于獲得線程ID,如果為NULL則不返回線程ID ) /* lpThreadAttributes:指向SECURITY_ATTRIBUTES結構的指針,決定返回的句柄是否可被子進程繼承,如果為NULL則表示返回的句柄不能被子進程繼承。 dwStackSize:設置初始棧的大小,以字節為單位,如果為0,那么默認將使用與調用該函數的線程相同的棧空間大小。 任何情況下,Windows根據需要動態延長堆棧的大小。 lpStartAddress:指向線程函數的指針,函數名稱沒有限制,但是必須以下列形式聲明: DWORD WINAPI 函數名 (LPVOID lpParam) ,格式不正確將無法調用成功。 lpParameter:向線程函數傳遞的參數,是一個指向結構的指針,不需傳遞參數時,為NULL。 dwCreationFlags:控制線程創建的標志,可取值如下: (1)CREATE_SUSPENDED(0x00000004):創建一個掛起的線程(就緒狀態),直到線程被喚醒時才調用 (2)0:表示創建后立即激活。 (3)STACK_SIZE_PARAM_IS_A_RESERVATION(0x00010000):dwStackSize參數指定初始的保留堆棧的大小, 如果STACK_SIZE_PARAM_IS_A_RESERVATION標志未指定,dwStackSize將會設為系統預留的值 lpThreadId:保存新線程的id 返回值:函數成功,返回線程句柄,否則返回NULL。如果線程創建失敗,可通過GetLastError函數獲得錯誤信息。 */ BOOL WINAPI CloseHandle(HANDLE hObject); //關閉一個被打開的對象句柄 /*可用這個函數關閉創建的線程句柄,如果函數執行成功則返回true(非0),如果失敗則返回false(0), 如果執行失敗可調用GetLastError.函數獲得錯誤信息。 */ ~~~ [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") **多線程編程實例1**: [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") ~~~ 1 #include <iostream> 2 #include <windows.h> 3 using namespace std; 4 5 DWORD WINAPI Fun(LPVOID lpParamter) 6 { 7 for (int i = 0; i < 10; i++) 8 cout << "A Thread Fun Display!" << endl; 9 return 0L; 10 } 11 12 int main() 13 { 14 HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL); 15 CloseHandle(hThread); 16 for (int i = 0; i < 10; i++) 17 cout << "Main Thread Display!" << endl; 18 return 0; 19 } ~~~ [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼")   **運行結果:**   ![](https://images2015.cnblogs.com/blog/763943/201609/763943-20160927113702094-347887715.png)   可以看到主線程(main函數)和我們自己的線程(Fun函數)是隨機交替執行的。可以看到Fun函數其實只運行了六次,這是因為主線程運行完之后將所占資源都釋放掉了,使得子線程還沒有運行完。看來主線程執行得有點快,讓它sleep一下吧。   使用函數Sleep來暫停線程的執行。 ~~~ 1 VOID WINAPI Sleep( 2 __in DWORD dwMilliseconds 3 ); ~~~ dwMilliseconds表示千分之一秒,所以 Sleep(1000); 表示暫停1秒。 **多線程編程實例2**: [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") ~~~ 1 #include <iostream> 2 #include <windows.h> 3 using namespace std; 4 5 DWORD WINAPI Fun(LPVOID lpParamter) 6 { 7 for (int i = 0; i < 10; i++) 8 { 9 cout << "A Thread Fun Display!" << endl; 10 Sleep(200); 11 } 12 13 return 0L; 14 } 15 16 int main() 17 { 18 HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL); 19 CloseHandle(hThread); 20 for (int i = 0; i < 10; i++) 21 { 22 cout << "Main Thread Display!" << endl; 23 Sleep(500); 24 } 25 26 return 0; 27 } ~~~ [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼")   **運行結果:**   ![](https://images2015.cnblogs.com/blog/763943/201609/763943-20160927114148360-2014650348.png)   程序是每當Fun函數和main函數輸出內容后就會輸出換行,但是我們看到的確是有的時候程序輸出換行了,有的時候確沒有輸出換行,甚至有的時候是輸出兩個換行。這是怎么回事?下面我們把程序改一下看看。 **多線程編程實例3**: [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") ~~~ 1 #include <iostream> 2 #include <windows.h> 3 using namespace std; 4 5 DWORD WINAPI Fun(LPVOID lpParamter) 6 { 7 for (int i = 0; i < 10; i++) 8 { 9 //cout << "A Thread Fun Display!" << endl; 10 cout << "A Thread Fun Display!\n"; 11 Sleep(200); 12 } 13 14 return 0L; 15 } 16 17 int main() 18 { 19 HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL); 20 CloseHandle(hThread); 21 for (int i = 0; i < 10; i++) 22 { 23 //cout << "Main Thread Display!" << endl; 24 cout << "Main Thread Display!\n"; 25 Sleep(500); 26 } 27 28 return 0; 29 } ~~~ [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼")   **運行結果****:**   ![](https://images2015.cnblogs.com/blog/763943/201609/763943-20160927114956531-1240548088.png)   這時候,正如我們預期的,正確地輸出了我們想要輸出的內容并且格式也是正確的。在這里,我們可以把屏幕看成是一個資源,這個資源被兩個線程所共用,加入當Fun函數輸出了Fun Display!后,將要輸出endl(也就是清空緩沖區并換行,在這里我們可以不用理解什么是緩沖區),但此時,main函數卻得到了運行的機會,此時Fun函數還沒有來得及輸出換行(**時間片用完**),就把CPU讓給了main函數,而這時main函數就直接在Fun Display!后輸出Main Display!。   另一種情況就是“輸出兩個換行”,這種情況就是比如輸出Main Display!并輸出endl后,時間片用完,輪到子線程占用CPU,子進程上一次時間片用完時停在了Fun Display!,下一次時間片過來時,剛好開始輸出endl,此時就會“輸出兩個換行”。   那么為什么我們把實例2改成實例3就可以正確的運行呢?原因在于,**多個線程雖然是并發運行的,但是有一些操作(比如輸出一整段內容)是必須一氣呵成的,不允許打斷的,所以我們看到實例2和實例3的運行結果是不一樣的。它們之間的差異就是少了endl,而多了一個換行符\\n**。   那么,是不是實例2的代碼我們就不可以讓它正確的運行呢?答案當然是否定的,下面我就來講一下怎樣才能讓實例2的代碼可以正確運行。這涉及到多線程的同步問題。對于一個資源被多個線程共用會導致程序的混亂,我們的解決方法是**只允許一個線程擁有對共享資源的獨占,這里我們用互斥量(Mutex)來進行線程同步**。   在使用互斥量進行線程同步時,會用到以下幾個函數: [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") ~~~ HANDLE WINAPI CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, //線程安全相關的屬性,常置為NULL BOOL bInitialOwner, //創建Mutex時的當前線程是否擁有Mutex的所有權 LPCTSTR lpName //Mutex的名稱 ); /* MutexAttributes:也是表示安全的結構,與CreateThread中的lpThreadAttributes功能相同,表示決定返回的句柄是否可被子進程繼承,如果為NULL則表示返回的句柄不能被子進程繼承。 bInitialOwner:表示創建Mutex時的當前線程是否擁有Mutex的所有權,若為TRUE則指定為當前的創建線程為Mutex對象的所有者,其它線程訪問需要先ReleaseMutex lpName:Mutex的名稱 */ ~~~ [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") ~~~ DWORD WINAPI WaitForSingleObject( HANDLE hHandle, //要獲取的鎖的句柄 DWORD dwMilliseconds //超時間隔 ); /* WaitForSingleObject:等待一個指定的對象(如Mutex對象),直到該對象處于非占用的狀態(如Mutex對象被釋放)或超出設定的時間間隔。除此之外,還有一個與它類似的函數WaitForMultipleObjects,它的作用是等待一個或所有指定的對象,直到所有的對象處于非占用的狀態,或超出設定的時間間隔。 hHandle:要等待的指定對象的句柄。 dwMilliseconds:超時的間隔,以毫秒為單位;如果dwMilliseconds為非0,則等待直到dwMilliseconds時間間隔用完或對象變為非占用的狀態,如果dwMilliseconds 為INFINITE則表示無限等待,直到等待的對象處于非占用的狀態。 */ ~~~ [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") ~~~ BOOL WINAPI ReleaseMutex(HANDLE hMutex); //說明:釋放所擁有的互斥量鎖對象,hMutex為釋放的互斥量句柄 ~~~ **多線程實例4**: [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼") ~~~ 1 #include <iostream> 2 #include <windows.h> 3 using namespace std; 4 5 HANDLE hMutex = NULL;//互斥量 6 //線程函數 7 DWORD WINAPI Fun(LPVOID lpParamter) 8 { 9 for (int i = 0; i < 10; i++) 10 { 11 //請求一個互斥量鎖 12 WaitForSingleObject(hMutex, INFINITE); 13 cout << "A Thread Fun Display!" << endl; 14 Sleep(100); 15 //釋放互斥量鎖 16 ReleaseMutex(hMutex); 17 } 18 return 0L;//表示返回的是long型的0 19 20 } 21 22 int main() 23 { 24 //創建一個子線程 25 HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL); 26 hMutex = CreateMutex(NULL, FALSE,"screen"); 27 //關閉線程 28 CloseHandle(hThread); 29 //主線程的執行路徑 30 for (int i = 0; i < 10; i++) 31 { 32 //請求獲得一個互斥量鎖 33 WaitForSingleObject(hMutex,INFINITE); 34 cout << "Main Thread Display!" << endl; 35 Sleep(100); 36 //釋放互斥量鎖 37 ReleaseMutex(hMutex); 38 } 39 return 0; 40 } ~~~ [![復制代碼](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0); "復制代碼")   **運行結果:**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看