程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> WINDOWS核心編程學習心得--線程調度

WINDOWS核心編程學習心得--線程調度

編輯:關於C語言

線程的主要有五種狀態

1.新建狀態:新創建了一個線程對象。

2.就緒狀態:線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。

3.運行狀態:就緒狀態的線程獲取了CPU,執行程序代碼。

4.阻塞狀態:阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。

5.掛起狀態:一般是指被掛起,因為同一時刻,需要“同步”運行的線程不止他一個,所以基於時間片輪轉的原則,他在獨占了一段時間的CPU後,被掛起,線程環境被壓棧。

下面就掛起和阻塞進行以下說明:

1.掛起是一種主動行為,因此恢復也應該要主動完成,而阻塞則是一種被動行為,是在等待事件或資源時任務的表現,你不知道他什麼時候被阻塞(pend),也就不能確切 的知道他什麼時候恢復阻塞。而且掛起隊列在操作系統裡可以看成一個,而阻塞隊列則是不同的事件或資源如信號量)就有自己的隊列。

2.阻塞pend)就是任務釋放CPU,其他任務可以運行,一般在等待某種資源或信號量的時候出現。掛起suspend)不釋放CPU,如果任務優先級高就永遠輪不到其他任務運行,一般掛起用於程序調試中的條件中斷,當出現某個條件的情況下掛起,然後進行單步調試。

3.pend是task主動去等一個事件,或消息.suspend是直接懸掛task,以後這個task和你沒任何關系,任何task間的通信或者同步都和這個suspended task沒任何關系了,除非你resume task;

4.任務調度是操作系統來實現的,任務調度時,直接忽略掛起狀態的任務,但是會顧及處於pend下的任務,當pend下的任務等待的資源就緒後,就可以轉為ready了。ready只需要等待CPU時間,當然,任務調度也占用開銷,但是不大,可以忽略。可以這樣理解,只要是掛起狀態,操作系統就不在管理這個任務了。

5.掛起是主動的,一般需要用掛起函數進行操作,若沒有resume的動作,則此任務一直不會ready。而阻塞是因為資源被其他任務搶占而處於休眠態。兩者的表現方式都是從就緒態裡“清掉”,即對應標志位清零,只不過實現方式不一樣。

這些術語是針對線程或進程來說的,比如有種叫法“進程三態”什麼的,但是不同的操作系統,或者同種操作系統不同版本見也存在狀態管理方式上的不同,比如還有什麼“進程五態”、“進程七態”的,我們可以把操作系統對進程的控制形象地比作雇人打工。

1、睡眠態:雇主對雇工說:“你睡覺去吧,某時某刻回來報道,接著干活!”

2、掛起態:雇主對雇工說:“你睡覺去吧,用得著你的時候,我會去叫你的,接著干活!”

3、就緒態:雇工的掃帚指CPU)被別的雇工搶了,自己只能按照規定的方式參與競爭比如Linux中是按時間片輪轉的方式),搶到就是自己的,然後接著干活!

4、阻塞態:雇工的抹布指非CPU的其他資源)被別的雇工搶了,自己只能干等著,等到了抹布,就進入就緒態,繼續參與到搶掃帚的競賽中。

這裡可以想象,睡眠和掛起應該是差不多的,睡眠應該是掛起多長時間後回來,但是他們都是一直占著CPU的。

WINDOWS不是實時操作系統,是搶占式的多線程操作系統,系統可以在任何時候停止一個線程調用另外的線程。


一個線程可以被掛起多次,SuspendThread多少次就要ResumeThread多少次,除了被別人調用SuspendThread掛起外,線程也可以告訴系統在一段時間內,可以將自己掛起,不需要調度。這可以調用Sleep實現。

void Sleep(DWORD dwMilliseconds);

這裡參數是表示線程要掛起多長時間,但是WINDOWS不是實時操作系統,不能保證到時候准時醒來,當為其傳入0時,表示主調線程主動放棄本次時間片的剩余部分。注意是本次。


當計算線程執行某任務所需的時間的時候,很多人習慣使用GetTickCount64

ULONG start=GetTickCount64();
  //do something.
ULONG end=GetTickCount64();

這個函數可能會由於線程中途被掛起而變得不准確,Windows提供了一個函數可以返回一個線程以獲得cpu時間

BOOL GetThreadTime(
        HANDLE hThread,
        PFILETIME pftCreationTime,
        PFILETIME pftExitTime,
       PFILETIME pftKernelTime,
       PFILETIME pftUserTime);

第一個參數為想獲得的線程句柄。

第二個參數返回線程創建時間-1601年1月1日0:00)的秒數。單位是100ns。

第三個表示退出時間-1601年1月1日0:00的秒數。單位是100ns。

第四個表示線程執行內核模式下的時間的絕對值。單位是100ns。

第五個表示線程執行用戶模式代碼的時間的絕對值。單位是100ns。

類似的,GetProcessTime可以返回進程中所有線程的時間之和。

在進行高精度的計算時上述函數仍然不夠。此時windows提供了以下函數:

BOOL QueryPerformanceFrequency(LARGE_INTEGER *pliFrequency)
BOOL  QueryPerformanceCounter(LARGE_INTEGER *pliCount);

這兩個函數假設正在執行的線程不會被搶占。它們都是針對生命期很短的代碼塊。GetCPUFrequencyInMHZ可以獲得cpu頻率。

本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1300631

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved