天天看點

線程優先級差别的實際作用

今天無聊就想随便測試一下所謂線程優先級的高低到底對時間片配置設定有多大影響,測試代碼如下:

DWORD CALLBACK thread_fun2 (LPVOID);

long i=0;

int cnt_1=0;

int cnt_2=0;

#define CNT 60000

DWORD CALLBACK thread_fun1 (LPVOID lpParam)

{

DWORD thread_id;

PHANDLE phThread2=(PHANDLE)lpParam;

SECURITY_ATTRIBUTES sa;

int i_bak=0;

sa.nLength=sizeof(SECURITY_ATTRIBUTES);

sa.bInheritHandle=TRUE;

sa.lpSecurityDescriptor=NULL;

*phThread2=CreateThread (&sa,0,thread_fun2,(LPVOID)NULL,CREATE_SUSPENDED,&thread_id);

SetThreadPriority (*phThread2,THREAD_PRIORITY_IDLE);

ResumeThread (*phThread2);

//Sleep (0);        //Sleep (1);

//for (int j=0;j<10000;j++)

// Sleep (0);

do

{

     i_bak=InterlockedExchangeAdd (&i,1);

     printf ("thread1:%d/n",i_bak);

     cnt_1++;

}while (i_bak<CNT);

printf ("thread1 ended!/n");

return 0;

}

DWORD CALLBACK thread_fun2 (LPVOID lpParam)

{

int i_bak=0;

//Sleep (0);

do

{

     i_bak=InterlockedExchangeAdd (&i,1);

     printf ("thread2:%d/n",i_bak);

     cnt_2++;

}while (i_bak<CNT);

printf ("thread2 ended!/n");

return 0;

}

int main ()

{

SECURITY_ATTRIBUTES sa;

sa.nLength=sizeof(SECURITY_ATTRIBUTES);

sa.bInheritHandle=TRUE;

sa.lpSecurityDescriptor=NULL;

DWORD thread_id;

HANDLE hThread2;

HANDLE hThread1=CreateThread (&sa,0,thread_fun1,(LPVOID)(&hThread2),CREATE_SUSPENDED,&thread_id);

SetThreadPriority (hThread1,THREAD_PRIORITY_BELOW_NORMAL);

ResumeThread (hThread1);

WaitForSingleObject (hThread1,INFINITE);

WaitForSingleObject (hThread2,INFINITE);

printf ("cnt_1:%d/tcnt_2:%d/n",cnt_1,cnt_2);      //線程1,2的執行次數

return 0;

}

        首先,用上面代碼運作肯定會出現CPU占用100%,但具體是哪個程序占用CPU呢?我一開始以為會是程序本身,常理就是如此,但實際上是CSRSS程序占用92%左右的CPU.

        CSRSS是作業系統負責處理圖形界面的程序.也就是說printf函數執行後程式等待CSRSS處理實際的輸出工作,程序本身已經被阻塞了,等待處理結果.等CSRSS處理完成後再激活阻塞程序,CSRSS程序扮演了低速IO終端的角色,整個過程類似于中斷,最忙碌的當然就會是CSRSS了.道理很簡單,隻是直覺認識錯誤罷了.

        其次,如果有printf語句,相同優先級線程1,2執行次數相差不多.但如果注釋掉的話,如果線程1優先級不夠高,線上程2執行完之前根本不會有機會得到執行.其中的互斥通路機制根本沒有任何作用,因為線程2線上程1建立2後的一個時間片裡已經執行完了所有循環.如果在2函數中加一句Sleep (0);也就是說放棄一次時間片,結果就反過來了.

         而且我發現假如1比2的優先級高一級,那麼直接2就沒機會執行了,如果在建立2後加一句Sleep (0);放棄一次時間片,仍是如此,但如果再加一句Sleep (0)就沒機會了,也就是說高一級作業系統會多配置設定兩個時間片.但假如高兩級,那麼即使for (int j=0;j<60000;j++)Sleep (0);這樣也沒辦法讓線程2争取到CPU,可見高兩級時作業系統絕對會先處理高優先的線程,哪怕前者放棄了如此多次的時間片.但是如果用一句Sleep (1),那麼高多少級都沒用了,可見1毫秒的時間實在是太長了.

          以上都是在單核處理器上測試的,用雙核的話肯定就不會如此了,有條件的可以在雙核上試一試,純粹娛樂吧.