1. 程式人生 > >多線程學習----CreateThread

多線程學習----CreateThread

lock num .cpp 發的 objects 獲取 cti del critical

tt.cpp : 定義控制臺應用程序的入口點。

同一進程中的多個線程將共享該進程中的全部系統資源,如虛擬地址空間、文件描述符和信號處理等,但是同一個進程中的多個線程都有各自的調用棧、寄存器環境和線程本地存儲。

線程都擁有自己的堆棧,臨界區等主要是控制訪問全局變量和成員變量

  1 #include "stdafx.h"
  2 #include <Windows.h>
  3 #include <stdio.h>
  4 #include <conio.h>
  5 
  6 #define WM_NIHAO  1001
  7 #define THREADNUM 3
  8
9 /* 10 volatile 修飾符的作用是告訴編譯器無需對該變量作任何的優化,即無需將它放到一個寄存器中,並且該值可被外部改變。 11 對於多線程引用的全局變量來說,volatile 是一個非常重要的修飾符。 12 */ 13 volatile int gInt=0; 14 //普通臨界區 15 static CRITICAL_SECTION cs; 16 //MFC臨界區 17 //CCriticalSection ccs; 18 19 //使用原子操作的方法 20 volatile LONG aomic=100; 21 22 void fun(int
tNum) 23 { 24 //printf("第%d線程已經工作了\n",tNum); 25 26 if (1) 27 { 28 //臨界區 29 EnterCriticalSection(&cs);// 進入臨界區,其它線程則無法進入 30 //ccs.Lock(); 31 // 安全訪問該區域 32 gInt--; 33 printf("第%d線程檢測到全局變量gInt的值是:%d\n",tNum,gInt); 34 Sleep(0);//致使不使用臨界區肯定出錯的方法
35 gInt++; 36 printf("第%d線程檢測到全局變量gInt的值是:%d\n",tNum,gInt); 37 //ccs.Unlock(); 38 LeaveCriticalSection(&cs); // 離開臨界區,其它線程可以進入 39 40 //原子操作 41 InterlockedIncrement(&aomic); 42 InterlockedDecrement(&aomic); 43 } 44 45 MSG msg; 46 //GetMessage 是 從調用線程的消息隊列裏取得一個消息並將其放於指定的結構。 47 //GetMessage不接收屬於其他線程或應用程序的消息。獲取消息成功後,線程將從消息隊列中刪除該消息。函數會一直等待直到有消息到來才有返回值。 48 //返回值:如果函數取得WM_QUIT之外的其他消息,返回非零值。如果函數取得WM_QUIT消息,返回值是零。如果出現了錯誤,返回值是-1。 49 while(1) 50 { 51 int tGM=::GetMessage(&msg,NULL,0,0); 52 switch(msg.message) 53 { 54 case WM_NIHAO: 55 printf("第%d線程接收到主線程的發過來的消息:%s\n",tNum,(char*)msg.wParam); 56 break; 57 default: 58 break; 59 } 60 61 //不需要接收第二次消息 62 if (tGM>0) 63 { 64 break; 65 } 66 } 67 68 printf("%d線程結束",tNum); 69 70 //該函數用於線程終結自身的執行,主要在線程的執行函數中被調用。其中參數dwExitCode用來設置線程的退出碼。 71 //ExitThread(1); 72 } 73 int _tmain(int argc, _TCHAR* argv[]) 74 { 75 // 在進入多線程環境之前,初始化臨界區 76 InitializeCriticalSection(&cs); 77 78 DWORD threadId[THREADNUM]; 79 HANDLE hThread[THREADNUM]; 80 for (int i=0;i<THREADNUM;i++) 81 { 82 hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fun,(LPVOID)i,CREATE_SUSPENDED,&(threadId[i])); 83 } 84 85 while (getch()!=1) 86 { 87 Sleep(100); 88 } 89 //試探線程讀取全局變量 90 gInt=100; 91 for (int i=0;i<THREADNUM;i++) 92 { 93 if (-1==ResumeThread(hThread[i])) 94 { 95 printf("ResumeThread時候出錯了\n"); 96 return -1; 97 } 98 99 } 100 //ResumeThread線程之後線程投入工作需要一定時間 101 Sleep(1000); 102 103 char buff[20]="ni hao ma?"; 104 for (int i=0;i<THREADNUM;i++) 105 { 106 BOOL bPostMes=PostThreadMessage(threadId[i],WM_NIHAO,(WPARAM)buff,(LPARAM)strlen(buff)); 107 } 108 //參數一:線程句柄 109 //參數二:等待時間(毫秒),IGNORE:不等,INFINITE:死等 110 //返回值: WAIT_OBJECT_0: 線程結束 111 // WAIT_TIMEOUT:超過等待時間,指定的對象處於無信號狀態 112 // WAIT_ABANDONED:WAIT_ABANDONED_0至(WAIT_ABANDONED_0 + nCount - 1)如果bWaitAll為TRUE,則返回值表明所有指定對象的狀態是觸發的,並且至少對象之一,是一個廢棄的互斥對象。 113 // WAIT_FAILED:出現錯誤,一般是線程句柄錯誤 114 //WaitForSingleObject函數,此函數的作用是監視hHandle的狀態,當監視的句柄為有信號狀態時,即此對象為空閑狀態時,此函數返回,才能執行其後的代碼。 115 //WaitForSingleObject(hThread,INFINITE); 116 117 Sleep(1000); 118 //值得註意的是hThread數組的所有成員必須全部有效,有一個沒效的話,次函數就會執行失敗 119 DWORD wm=WaitForMultipleObjects(THREADNUM,hThread,true,10000); 120 //若果第三個參數是true,則返回值代表所有線程的狀態 121 //若果第三個參數是false,則返回值代表那個有返回線程的狀態 122 switch (wm) 123 { 124 case WAIT_FAILED: 125 printf("wm-->WAIT_FAILED\n"); 126 break; 127 case WAIT_TIMEOUT: 128 printf("wm-->WAIT_TIMEOUT\n"); 129 break; 130 131 case WAIT_ABANDONED_0+0: 132 case WAIT_ABANDONED_0+1: 133 case WAIT_ABANDONED_0+2: 134 printf("wm-->WAIT_ABANDONED_0\n"); 135 break; 136 137 case WAIT_OBJECT_0+0: 138 case WAIT_OBJECT_0+1: 139 case WAIT_OBJECT_0+2: 140 printf("wm-->WAIT_OBJECT_0\n"); 141 break; 142 143 default: 144 break; 145 } 146 147 //一般情況下,線程運行結束之後,線程函數正常返回,但是應用程序可以調用TerminateThread強行終止某一線程的執行。 148 for (int i=0;i<THREADNUM;i++) 149 { 150 TerminateThread(hThread[i],0); 151 } 152 153 // 釋放臨界區資源,當不再使用臨界區時調用該函數 154 DeleteCriticalSection(&cs); 155 return 0; 156 }

多線程學習----CreateThread