第七章 線程調(diào)度、優(yōu)先級、親和力
1.掛起和恢復(fù)線程
(1)ResumeThread
被掛起的線程不會被調(diào)度,只有線程調(diào)用ResumeThread()的次數(shù)等于SuspendThread()時,線程才會被調(diào)度。
線程可以Suspend自已但是不能Resume自已。因為被掛起后不會被調(diào)度,從而不會執(zhí)行線程函數(shù)內(nèi)的代碼.
(2)SuspendThread
掛起線程時一定要小心 必須明確知道線程在干什么才能決定是否掛起線程。因為當(dāng)線程正在堆分配內(nèi)存時,它會給這個堆加上鎖。
此時如果將線程掛起,其它線程若想在堆上分配內(nèi)存則會進(jìn)入無限等待 直到堆的鎖被掛起的線程解開。從而導(dǎo)致死鎖。
2.掛起和恢復(fù)進(jìn)程
Windows中并不存在掛起和恢復(fù)進(jìn)程的概念。因為Windows中是以線程為單位來調(diào)度和分配CPU的。進(jìn)程只相當(dāng)于是一個承載線程的容器,系統(tǒng)不會給進(jìn)程分配任何CPU.
我們可以把掛起進(jìn)程理解為掛起進(jìn)程中所有的線程。Windows并沒有提供此類API,但是我們可以通過CreateToolhelp32Snapshot()來實現(xiàn)我們自制的SuspendProcess().
因為CreateToolhelp32Snapshot只是創(chuàng)建某個進(jìn)程在某一時刻的快照(如進(jìn)程占有的內(nèi)存,進(jìn)程中有多少正在運(yùn)行的線程)。
然后通過Thread32First()和Thread32Next()來遍歷快照中所得的所有線程。
這么做容易出一些問題 比如通過Thread32Next()取得線程ID后 線程可能立刻就終止了。同樣隨時會有新的線程產(chǎn)生,而快照中不會反應(yīng)有出新產(chǎn)生的線程,
從而也就無法掛起該線程。
3.Sleep和SwitchThread
(1)Sleep
線程調(diào)用Sleep函數(shù)后會進(jìn)入睡眠狀態(tài) 系統(tǒng)會不調(diào)度該進(jìn)程。
Sleep(0)的意思是讓當(dāng)前線程讓出CPU給同或高優(yōu)先級線程用,但不會把CPU讓給比優(yōu)先級低級的線程。
(2)SwitchThread
與Sleep(0)相同,SwitchThread會迫使當(dāng)前線程讓出CPU級其它線程用。若無其它線程則該函數(shù)立即返回。
不同的是SwitchThread允許低優(yōu)先級的線程使用CPU.
4.優(yōu)先級
(1)設(shè)置優(yōu)先級
線程的優(yōu)先級和進(jìn)程的優(yōu)先級是相關(guān)的。改變進(jìn)程的優(yōu)先級會同時改變線程的優(yōu)先級。也可把進(jìn)程的優(yōu)先稱做線程的基優(yōu)先級。
雖然進(jìn)程有優(yōu)先級但進(jìn)程并不可調(diào)度,進(jìn)程優(yōu)先級只是種抽象的概念,幫助我們脫離調(diào)度器的內(nèi)部工作原理。
SetPriorityClass和GetPriorityClass用來設(shè)置和獲得進(jìn)程的優(yōu)先級。
SetThreadPriority和GetThreadPriority用來設(shè)置和獲得線程的優(yōu)先級。
(2)動態(tài)提升優(yōu)先級
默認(rèn)情況下Windows會動態(tài)提升一些線程或進(jìn)程的優(yōu)先級從而避免當(dāng)高線程優(yōu)先級壟斷CPU.
提高低線程的優(yōu)先級讓它獲取CPU.當(dāng)線程執(zhí)釋放CPU時會立刻降到原來的優(yōu)先級。
我們可以能過以下方法來設(shè)置或獲取線程或進(jìn)程的動態(tài)優(yōu)先級設(shè)置。從而允許或禁止系統(tǒng)動態(tài)提升優(yōu)先級。
SetProcessPriorityBoost,SetThreadPriorityBoost
GetProcessPriorityBoost,GetThreadPriorityBoost
a thread is not allowed to change the I/O priority of another thread.
Code example:
DWORD dwThreadID;
HANDLE hThread = CreateThread(NULL, 0, ThreadFunc, NULL,CREATE_SUSPENDED, &dwThreadID);
SetThreadPriority(hThread, THREAD_PRIORITY_IDLE);
ResumeThread(hThread);
CloseHandle(hThread);
5.Affinity
SetProcessAffinityMask 限制某進(jìn)程中的線程 只能在指定的幾個CPU上運(yùn)行。也用通過Job內(nèi)核對象限制Job中的所有進(jìn)程只能在指定的CPU上運(yùn)行。
SetThreadAffinityMask 限制線程只能在指定的CPU上運(yùn)行。其被指定的CPU必須是進(jìn)程所指定的CPU的子集。
GetSystemInfo() 查看CPU信息
6.Common API:
DWORD ResumeThread(HANDLE hThread);
DWORD SuspendThread(HANDLE hThread);
CreateToolhelp32Snapshot()
Thread32First()
Thread32Next()
Sleep()
GetThreadContext()
SetThreadContext()