スレッドが作成されると、すぐに実行されるとは限りません.



スレッドの作成は、すぐに実行するのではなく、タイムスライスが来てから実行します.
 
複数のスレッドを含むプロセス.
このスレッドはプロセスのデータなどのリソースを共有し,各スレッドは同時実行状態を呈する.
スレッドの実行時に入力されるパラメータ値は、スレッドの作成時に入力されるのではなく、実行時に入力されます.
 
 
次の手順を考慮します.
 
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <process.h>

using namespace std;

long g_nNum;
unsigned int _stdcall ThreadFun(void *pPM);
const int THREAD_NUM=10;
CRITICAL_SECTION g_csThreadCore;
HANDLE hSemaphore;

 
int main(array<System::String ^> ^args)
{
	g_nNum=0;
	HANDLE handle[10];
	int i=0;

	// 
	InitializeCriticalSection(&g_csThreadCore);
	// 
	hSemaphore=CreateSemaphore(NULL,0,1,NULL);


	while(i<THREAD_NUM)
	{
		handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);
	//	WaitForSingleObject(hSemaphore,INFINITE);
		i++;
	}

	WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);

	DeleteCriticalSection(&g_csThreadCore);
	CloseHandle(hSemaphore);
 

	cin>>i;
    return 0;
}


unsigned int _stdcall  ThreadFun(void *pPM)
{

	int nThreadnum=*(int*)pPM;
	ReleaseSemaphore(hSemaphore,1,NULL);
	
	//Sleep(50);
	EnterCriticalSection(&g_csThreadCore);
	g_nNum++;
//	Sleep(50);
	printf(" %d   %d
",nThreadnum,g_nNum); LeaveCriticalSection(&g_csThreadCore); return 0; }

 
  
実行結果:
 
スレッド番号7グローバルリソース値1スレッド番号7グローバルリソース値2スレッド番号8グローバルリソース値3スレッド番号7グローバルリソース値4スレッド番号7グローバルリソース値5スレッド番号7グローバルリソース値6スレッド番号10グローバルリソース値7スレッド番号10グローバルリソース値8スレッド番号7グローバルリソース値9スレッド番号7グローバルリソース値7グローバルリソース値10
スレッド番号が正しくありません.理由は次のとおりです.
スレッドを作成すると、すぐに実行されず、実行するとパラメータの値が変更されます.
また、スレッド番号には重複値があります.これは、i値が変更される前に、いくつかのスレッドが起動され、これらのスレッドに入力された値がi(番号)であるため、スレッド番号の重複問題が発生することを示します.
たとえば、i=0の場合、スレッド0が作成されます.
i=1の場合、スレッド1を作成する
i=2の場合、スレッド2を作成する
ただし、この時点ではスレッド実行は1つも行われておらず、i=3の場合、スレッド3が作成され、
このとき、タイムスライスはスレッドの番になっているので、スレッド0が実行を開始する可能性があるが、スレッド0が実行されると、現在のiの値3が入力されるため、スレッド0の番号が3に誤って変更され、このスレッドは実行が完了せず、他のスレッド、例えばスレッド1が起動されるが、スレッド1が入力するパラメータもiの現在値3である
 
スレッド番号を正しくするにはどうすればいいですか?
正しく表示されないのは、スレッド実行時に正しいi値が入力されないためです.
したがって,スレッド作成が正常に実行されたときに正しい値が入力されると,この問題は解決する.
正しい値をどのように入力しますか?
handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);
i++;
スレッドiを作成します.このスレッドは作成後、すぐに実行されるのではなく、直接i++で別のスレッドを作成します.
i++の前にこのスレッドが実行されていることを確認できれば、正しいi値が入力されます...
 
  handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);   WaitForSingleObject(hSemaphore,INFINITE);   i++;
 
WaitForSingleObject(hSemaphore,INFINITE);
hSemaphoreに信号があるまで下に進み、作成したスレッドが実行される場合にのみSemaphoreに信号があります.
スレッド関数には信号を設定する関数があるからです:ReleaseSemaphore(hSemaphore,1,NULL);
 
これにより、スレッド番号の正確さが保証されます.
 
int main(array<System::String ^> ^args)
{
	g_nNum=0;
	HANDLE handle[10];
	int i=0;

	// 
	InitializeCriticalSection(&g_csThreadCore);
	// 
	hSemaphore=CreateSemaphore(NULL,0,1,NULL);


	while(i<THREAD_NUM)
	{
		handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);
		WaitForSingleObject(hSemaphore,INFINITE);
		i++;
	}

	WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);

	DeleteCriticalSection(&g_csThreadCore);
	CloseHandle(hSemaphore);
 

	cin>>i;
    return 0;
}

スレッド番号0グローバルリソース値1スレッド番号1グローバルリソース値2スレッド番号2グローバルリソース値3スレッド番号3グローバルリソース値4スレッド番号4グローバルリソース値5スレッド番号5グローバルリソース値6スレッド番号6グローバルリソース値7スレッド番号7グローバルリソース値8スレッド番号8グローバルリソース値9スレッド番号9グローバルリソース値10
注意:スレッド関数には信号量の設定に加えて、臨界領域が設定されています.臨界領域には1つのスレッドしかアクセスできません.
1つのスレッドが臨界領域に入ると、他のスレッドは臨界領域を終了してからアクセスするしかありません.
これにより,臨界領域内のグローバルデータが複数のスレッドによって同時に修正されず,臨界領域内のプログラム順序の実行が保証される.
 
	EnterCriticalSection(&g_csThreadCore);
	g_nNum++;
	printf(" %d   %d
",nThreadnum,g_nNum); LeaveCriticalSection(&g_csThreadCore);

もし:臨界領域を取り除く
スレッド番号3グローバルリソース値4スレッド番号2グローバルリソース値1スレッド番号0グローバルリソース値2スレッド番号1グローバルリソース値3スレッド番号8グローバルリソース値5スレッド番号9グローバルリソース値6スレッド番号6グローバルリソース値8スレッド番号7グローバルリソース値6スレッド番号6グローバルリソース値4グローバルリソース値9
このように、グローバルリソースの順序が間違っており、重複する現象もあります.
これは、各スレッドがグローバル変数に同時にアクセスするため、一貫性がありません.
 
参考資料:http://blog.sina.com.cn/s/blog_6120646301012szj.html