天天看點

3、多線程(1)

一、概念

1、程序:通常被定義為一個正在運作的程式的執行個體,是一個程式在其自身的位址空間中的一次執行活動。一個程式可以有多個程序執行個體。

2、程序由兩個部分組成:

1)作業系統用來管理程序的核心對象。核心對象也是系統用來存放關于程序的統計資訊的地方。

2)位址空間。它包含所有可執行子產品或DLL子產品的代碼和資料。它還包含動态記憶體配置設定的空間。如線程堆棧和堆配置設定空間。

    程序從來不執行任何東西,它隻是線程的容器。若要使程序完成某項操作,它必須擁有一個在它的環境中運作的線程,此線程負責執行包含在程序的位址空間中的代碼。

    單個程序可能包含若幹個線程,這些線程都“同時”執行程序位址空間中的代碼。

每個程序至少擁有一個線程,來執行程序的位址空間中的代碼。當建立一個程序時,作業系統會自動建立這個程序的第一個線程,稱為主線程。此後,該線程可以建立其他的線程。

一個程序不能讀取、寫入、或者以任何方式通路駐留在該分區中的另一個程序的資料。

3、線程由兩個部分組成:

1)線程的核心對象,作業系統用它來對線程實施管理。核心對象也是系統用來存放線程統計資訊的地方。

2)線程堆棧,它用于維護線程在執行代碼時需要的所有參數和局部變量。

    線程總是在某個程序環境中建立。系統從程序的位址空間中配置設定記憶體,供線程的堆棧使用。新線程運作的程序環境與建立線程的環境相同。是以,新線程可以通路程序的核心對象的所有句柄、程序中的所有記憶體和在這個相同的程序中的所有其他線程的堆棧。這使得單個程序中的多個線程确實能夠非常容易地互相通信。

線程隻有一個核心對象和一個堆棧,保留的記錄很少,是以所需要的記憶體也很少。因為線程需要的開銷比程序少,是以在程式設計中經常采用多線程來解決程式設計問題,而盡量避免建立新的程序。

作業系統為每一個運作線程安排一定的CPU時間 —— 時間片。

二、線程程式設計

用CreateThread來建立線程。

Main函數是主線程的入口函數。新建立的線程也需要一個入口函數,就在下面的lpStartAddress中定義。

HANDLE CreateThread(

  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD

  DWORD dwStackSize,                        // initial stack size

  LPTHREAD_START_ROUTINE lpStartAddress,    // thread function

  LPVOID lpParameter,                       // thread argument

  DWORD dwCreationFlags,                    // creation option

  LPDWORD lpThreadId                        // thread identifier

);

lpThreadId  用來接收線程的ID。

DWORD WINAPI ThreadProc( LPVOID lpParameter );

類型和參數要比對,函數名任意。

關閉線程句柄

BOOL CloseHandle( HANDLE hObject );

注意:關閉句柄并沒有終止新建立的線程。隻是表示對新建立的線程的引用不敢興趣,系統會遞減新

線程的線程核心對象的使用計數。當使用計數為0的時候,系統就會釋放線程核心對象。如果在主線程中沒有關閉線程的句柄,始終都會保留一個引用。這樣線程核心對象的引用計數就不會為0。即使新線程執行完畢,線程核心對象也不會被釋放,隻有等到程序終止的時候系統才會為殘留的對象做清理工作。是以應該在不再使用線程的句柄的時候将其關閉掉,讓線程的線程核心對象的引用計數減1。

每個線程有一個引用記數器,當建立成功時初值為2,當你調用一次CloseHandle()時,計數器減一,如果為0,清除線程。線程執行完成計數器還是要減一,如果為0,清除線程。

暫停線程的執行

當線程暫停執行的時候,也就是表示它放棄了執行的權力。作業系統會從等待運作的線程隊列中選擇一個線程來運作。新建立的線程就可以得到運作的機會。

可以使用函數Sleep:

void Sleep( DWORD dwMilliseconds //sleep time 以毫秒為機關 );

暫停目前線程指定時間間隔的執行。

參考

[1] 孫鑫 《深入VC++》

繼續閱讀