多線程編程基礎知識

多線程編程基礎知識

當前流行的Windows操作系統能同時運行幾個程序(獨立運行的程序又稱之爲進程),對於同一個程序,它又可以分成若干個獨立的執行流,我們稱之爲線程,線程提供了多任務處理的能力。用進程和線程的觀點來研究軟件是當今普遍採用的方法,進程和線程的概念的出現,對提高軟件的並行性有着重要的意義。現在的大型應用軟件無一不是多線程多任務處理,單線程的軟件是不可想象的。因此掌握多線程多任務設計方法對每個程序員都是必需要掌握的。本實例針對多線程技術在應用中經常遇到的問題,如線程間的通信、同步等,分別進行探討,並利用多線程技術進行線程之間的通信,實現了數字的簡單排序。   

  一、 實現方法

  1、理解線程

  要講解線程,不得不說一下進程,進程是應用程序的執行實例,每個進程是由私有的虛擬地址空間、代碼、數據和其它系統資源組成。進程在運行時創建的資源隨着進程的終止而死亡。線程的基本思想很簡單,它是一個獨立的執行流,是進程內部的一個獨立的執行單元,相當於一個子程序,它對應於Visual C++中的CwinThread類對象。單獨一個執行程序運行時,缺省地包含的一個主線程,主線程以函數地址的形式出現,提供程序的啓動點,如main()或WinMain()函數等。當主線程終止時,進程也隨之終止。根據實際需要,應用程序可以分解成許多獨立執行的線程,每個線程並行的運行在同一進程中。

  一個進程中的所有線程都在該進程的虛擬地址空間中,使用該進程的全局變量和系統資源。操作系統給每個線程分配不同的CPU時間片,在某一個時刻,CPU只執行一個時間片內的線程,多個時間片中的相應線程在CPU內輪流執行,由於每個時間片時間很短,所以對用戶來說,彷彿各個線程在計算機中是並行處理的。操作系統是根據線程的優先級來安排CPU的時間,優先級高的線程優先運行,優先級低的線程則繼續等待。

  線程被分爲兩種:用戶界面線程和工作線程(又稱爲後臺線程)。用戶界面線程通常用來處理用戶的輸入並響應各種事件和消息,其實,應用程序的主執行線程CWinAPP對象就是一個用戶界面線程,當應用程序啓動時自動創建和啓動,同樣它的終止也意味着該程序的結束,進程終止。工作線程用來執行程序的後臺處理任務,比如計算、調度、對串口的讀寫操作等,它和用戶界面線程的區別是它不用從CWinThread類派生來創建,對它來說最重要的是如何實現工作線程任務的運行控制函數。工作線程和用戶界面線程啓動時要調用同一個函數的不同版本;最後需要讀者明白的是,一個進程中的所有線程共享它們父進程的變量,但同時每個線程可以擁有自己的變量。 

  2、線程的管理和操作

  (一)線程的啓動

  創建一個用戶界面線程,首先要從類CwinThread產生一個派生類,同時必須使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE來聲明和實現這個CwinThread派生類。第二步是根據需要重載該派生類的一些成員函數如:ExitInstance()、InitInstance()、OnIdle()、PreTranslateMessage()等函數。最後調用AfxBeginThread()函數的一個版本:CWinThread*AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority =THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0,LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ) 啓動該用戶界面線程,其中第一個參數爲指向定義的用戶界面線程類指針變量,第二個參數爲線程的優先級,第三個參數爲線程所對應的堆棧大小,第四個參數爲線程創建時的附加標誌,缺省爲正常狀態,如爲CREATE_SUSPENDED則線程啓動後爲掛起狀態。

  對於工作線程來說,啓動一個線程,首先需要編寫一個希望與應用程序的其餘部分並行運行的函數如Fun1(),接着定義一個指向CwinThread對象的指針變量*pThread,調用AfxBeginThread(Fun1,param,priority)函數,返回值賦給pThread變量的同時一併啓動該線程來執行上面的Fun1()函數,其中Fun1是線程要運行的函數的名字,也既是上面所說的控制函數的名字,param是準備傳送給線程函數Fun1的任意32位值,priority則是定義該線程的優先級別,它是預定義的常數,讀者可參考MSDN。

  (二)線程的優先級

  以下的CwinThread類的成員函數用於線程優先級的操作:

int GetThreadPriority();
BOOL SetThradPriority()(int nPriority);
  上述的二個函數分別用來獲取和設置線程的優先級,這裏的優先級,是相對於該線程所處的優先權層次而言的,處於同一優先權層次的線程,優先級高的線程先運行;處於不同優先權層次上的線程,誰的優先權層次高,誰先運行。至於優先級設置所需的常數,自己參考MSDN就可以了,要注意的是要想設置線程的優先級,這個線程在創建時必須具有THREAD_SET_INFORMATION訪問權限。對於線程的優先權層次的設置,CwinThread類沒有提供相應的函數,但是可以通過Win32 SDK函數GetPriorityClass()和SetPriorityClass()來實現。

  (三)線程的懸掛和恢復

  CWinThread類中包含了應用程序懸掛和恢復它所創建的線程的函數,其中SuspendThread()用來懸掛線程,暫停線程的執行;ResumeThread()用來恢復線程的執行。如果你對一個線程連續若干次執行SuspendThread(),則需要連續執行相應次的ResumeThread()來恢復線程的運行。

  (四)結束線程

  終止線程有三種途徑,線程可以在自身內部調用AfxEndThread()來終止自身的運行;可以在線程的外部調用BOOL TerminateThread( HANDLE hThread,DWORD dwExitCode )來強行終止一個線程的運行,然後調用CloseHandle()函數釋放線程所佔用的堆棧;第三種方法是改變全局變量,使線程的執行函數返回,則該線程終止。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章