第111章 スレッドの優先順位 その1


複数の子スレッドが存在する場合、優先順位を指定することができます。



THREAD_PRIORITY_HIGHEST(+2)
THREAD_PRIORITY_ABOVE_NORMAL(+1)
THREAD_PRIORITY_NORMAL(0)
THREAD_PRIORITY_BELOW_NORMAL(-1)
THREAD_PRIORITY_LOWEST(-2)
THREAD_PRIORITY_IDLE(1)
THREAD_PRIORITY_TIME_CRITICAL(15)

の7つがあります。()内の数値は+であれば相対優先度を上げ、マイナスであれば 優先度を下げることを意味します。

最後の2つは、優先度そのものを指定します。

スレッドに優先順位を指定するにはSetThreadPriority関数を使います。

BOOL SetThreadPriority(
  HANDLE hThread, // スレッドハンドル
  int nPriority   // スレッドの相対優先順位値
);
dwDesiredAccessに、アクセス権を指定します。

これには、

SYNCHRONIZE 待機関数で使用できるようにする
THREAD_ALL_ACCESSすべてのアクセスフラグを獲得します。
THREAD_GET_CONTEXTスレッドハンドルをGetThreadContext関数で使えるようにします。
THREAD_QUERY_INFORMATIONスレッドハンドルで終了コードなどの情報を読み取れるようにします。
THREAD_SET_CONTEXTスレッドハンドルをGetThreadContext関数で使えるようにします。
THREAD_SET_INFORMATIONスレッドハンドルで特定の情報を設定できるようにします。
THREAD_SET_THREAD_TOKENスレッドハンドルをSetTokenInformation関数で使えるようにします。
THREAD_SUSPEND_RESUMEスレッドハンドルをSuspendThread関数や、ResumeThread関数で使えるようにします。
THREAD_TERMINATEスレッドハンドルをTerminateThread 関数で使えるようにします。

などがあります。

bInheritHandleには、取得したハンドルを新しいプロセスに継承できるかどうかを指定します。

dwThreadIdには、スレッドIDを指定します。

関数が成功するとスレッドハンドルが返されます。 失敗するとNULLが返されます。

では、サンプルのプログラムを見てみましょう。

// priority.c
#define MYMAX 3000

#include <stdio.h>
#include <process.h>
#include <windows.h>

unsigned __stdcall mythread0(void *);
unsigned __stdcall mythread1(void *);
unsigned __stdcall mythread2(void *);
unsigned __stdcall mythread3(void *);


LONG lAdd = 0;
int n = 0;

int main()
{
	HANDLE hTh[4];
	DWORD dwID[4];
	int i;

	_beginthreadex(
        NULL ,
        0,
        mythread0,
        NULL,
        CREATE_SUSPENDED,
        &dwID[0]
    );
	_beginthreadex(
        NULL,
        0,
        mythread1,
        NULL,
        CREATE_SUSPENDED,
        &dwID[1]
    );
	_beginthreadex(
        NULL,
        0,
        mythread2,
        NULL,
        CREATE_SUSPENDED,
        &dwID[2]
    );
	_beginthreadex(
        NULL,
        0,
        mythread3,
        NULL,
        CREATE_SUSPENDED,
        &dwID[3]
    );

	hTh[0] = OpenThread(SYNCHRONIZE | STANDARD_RIGHTS_REQUIRED | THREAD_SUSPEND_RESUME | THREAD_SET_INFORMATION, TRUE, dwID[0]);
	hTh[1] = OpenThread(SYNCHRONIZE | STANDARD_RIGHTS_REQUIRED | THREAD_SUSPEND_RESUME | THREAD_SET_INFORMATION, TRUE, dwID[1]);
	hTh[2] = OpenThread(SYNCHRONIZE | STANDARD_RIGHTS_REQUIRED | THREAD_SUSPEND_RESUME | THREAD_SET_INFORMATION, TRUE, dwID[2]);
	hTh[3] = OpenThread(SYNCHRONIZE | STANDARD_RIGHTS_REQUIRED | THREAD_SUSPEND_RESUME | THREAD_SET_INFORMATION, TRUE, dwID[3]);

	SetThreadPriority(hTh[0], THREAD_PRIORITY_IDLE);
	SetThreadPriority(hTh[1], THREAD_PRIORITY_LOWEST);
	SetThreadPriority(hTh[2], THREAD_PRIORITY_HIGHEST);
	SetThreadPriority(hTh[3], THREAD_PRIORITY_TIME_CRITICAL);

	for (i = 0; i < 4; i++)
        ResumeThread(hTh[i]);
	
	WaitForMultipleObjects(3, hTh, TRUE, INFINITE);

	for (i = 0; i < 4; i++)        
        CloseHandle(hTh[i]);

	return 0;
}

unsigned __stdcall mythread0(void *lpx)
{
	int n = 0;

	while (lAdd < MYMAX) {
		lAdd++;
		n++;
		printf("thread0--%d\n", lAdd);
		Sleep(10);
	}
	printf("thread0は%d回\n", n);
	return 0;
}

unsigned __stdcall mythread1(void *lpx)
{
	int n = 0;

	while (lAdd < MYMAX) {
		lAdd++;
		n++;
		printf("thread1--%d\n", lAdd);
		Sleep(10);
	}
	printf("thread1は%d回\n", n);
	return 0;
}

unsigned __stdcall mythread2(void *lpx)
{
	int n = 0;

	while (lAdd < MYMAX) {
		lAdd++;
		n++;
		printf("thread2--%d\n", lAdd);
		Sleep(10);
	}
	printf("thread2は%d回\n", n);
	return 0;
}

unsigned __stdcall mythread3(void *lpx)
{
	int n = 0;

	while (lAdd < MYMAX) {
		lAdd++;
		n++;
		printf("thread3--%d\n", lAdd);
		Sleep(10);
	}
	printf("thread3は%d回\n", n);
	return 0;
}

各スレッドは、共通のグローバル変数lAddにアクセスしてその値を1増やします。

これが、MYMAXに達するとスレッドは終了します。

共通変数に、各スレッドが勝手にアクセスするのでおかしなことが起ることもあります。 (lAddの値が重複するなど)

各スレッドが何回共通変数にアクセスして値を増やしたかを最後に表示するようにします。

当然優先順位の高いスレッドが多くアクセスするはずです。

実験してみるとわかりますが、マシンスペックに余裕がある場合はほとんど差がつきません。動作中に、重たいソフトを動かすなどすると、優先順位の高いスレッドほどアクセス回数が多くなります。


[Index][総合Index] [Previous Chapter] [Next Chapter]

Update May/17/2005 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。