線程


一、什么是線程?

1、線程是附屬在進程上的執行實體,是代碼的執行流程。

2、一個進程可以包含多個線程,但一個進程至少要包含一個線程

3、線程是靠CPU調度的,如果CPU沒有空閑,線程被創建也不會被執行

4、如下就是個單線程

#include "stdafx.h"

int main(int argc, char* argv[])
{

	for(int i=0;i<100;i++)
	{
		printf("-------%d\n",i);

	}

	return 0;
}

二、創建線程函數

HANDLE CreateThread(
  	LPSECURITY_ATTRIBUTES lpThreadAttributes, 	// SD(安全描述符)
  	SIZE_T dwStackSize,                       	// initial stack size(創建線程初始堆棧)
  	LPTHREAD_START_ROUTINE lpStartAddress,    	// thread function(要執行的代碼在哪里,就是函數)
  	LPVOID lpParameter,                       	// thread argument(創建線程參數,可有可無)
  	DWORD dwCreationFlags,                    	// creation option(線程標識,狀態,比如設置為0,是創建之后,立即可以被調度)
  	LPDWORD lpThreadId                        	// thread identifier(線程ID)
);

三、線程函數

#include <windows.h>

//lpParameter是創建線程函數傳過來的參數
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{

}

四、多線程

圖形化界面,每創建一個功能就用多線程,不然容易造成主函數掛掉

#include "stdafx.h"
#include <windows.h>

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
	for(int i=0;i<100;i++)
		{
			printf("++++%d\n",i);
		}
	return 0;

}

int main(int argc, char* argv[])
{

	HANDLE hThread;
	hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);

	for(int i=0;i<100;i++)
	{
		printf("-------%d\n",i);
	}
	return 0;
}

五、傳遞參數

1、全局變量傳參

#include "stdafx.h"
#include <windows.h>

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
	int* x = (int*)lpParameter;
	for(int i=0;i<100;i++)
		{
			printf("++++%d\n",*x);
		}
	return 0;

}

int x = 2;

int main(int argc, char* argv[])
{

	HANDLE hThread;
	hThread = CreateThread(NULL,0,ThreadProc,&x,0,NULL);

	getchar();
	return 0;
}

2、局部變量傳參

傳遞的參數,需要保證比你創建的線程生命周期要長,不然就會出現傳入的參數地址被回收

六、線程ID

1、窗口和線程都不是在我們用戶層創建的,是在內核中創建的,我們沒有辦法去訪問內核,操作系統給我們一個編號(句柄),我們通過這個編號去訪問

2、線程ID是身份證,唯一的,系統進行線程調度的時候要使用的.

七、CloseHandle

CloseHandle(hThread)只是將編號不用了,不代表線程掛掉了


#include "stdafx.h"
#include <windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
	for(int i=0;i<100;i++)
		{
			Sleep(500);
			printf("++++%d\n",i);
		}
	return 0;

}

int main(int argc, char* argv[])
{

	HANDLE hThread;
	hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
	CloseHandle(hThread);
	for(int i=0;i<100;i++)
	{
		Sleep(500);
		printf("-------%d\n",i);
	}
	return 0;
}

八、線程掛起和恢復

演示:

1、為了演示效果明顯,創建線程后,停5秒Sleep(5000)

2、將線程掛起SuspendThread(hThread)

3、然后在停5秒Sleep(5000)

4、線程恢復ResumeThread(hThread)

5、關閉線程CloseHandle(hThread)(線程關閉,只要代碼沒執行完,內核並不會移出)

6、讓主線程main停下,getchar()(如果不停下,主線程跑完了,程序就關閉了,創建的線程就執行不了)

#include "stdafx.h"
#include <windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{

	int* p = (int*)lpParameter;
	for(int i=0;i<*p;i++)
		{
			Sleep(500);
			printf("++++%d\n",i);
		}
	return 0;

}


int main(int argc, char* argv[])
{

	HANDLE hThread;
	int n = 100;
	hThread = CreateThread(NULL,0,ThreadProc,(LPVOID)&n,0,NULL);
	Sleep(5000);
        //掛起
	SuspendThread(hThread);
	Sleep(5000);
        //恢復
	ResumeThread(hThread);
	CloseHandle(hThread);
	getchar();
	return 0;
}

九、線程阻塞

1、WaitForSingleObject

WaitForSingleObject函數是用來阻塞的,只有當線程狀態發生改變或者是等待時間到了,代碼才會繼續往下執行,否則就會處於阻塞狀態

WaitForSingleObject有兩個參數,第一個是線程的句柄,第二個是等待時間(INFINITE是一直等待,設置時間為毫秒)

#include "stdafx.h"
#include <windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{

	int* p = (int*)lpParameter;
	for(int i=0;i<*p;i++)
		{
			Sleep(50);
			printf("++++%d\n",i);
		}
	return 0;

}

int main(int argc, char* argv[])
{

	HANDLE hThread;
	int n = 100;
	hThread = CreateThread(NULL,0,ThreadProc,(LPVOID)&n,0,NULL);
	WaitForSingleObject(hThread,INFINITE);
	printf("線程結束 ");
	CloseHandle(hThread);
	getchar();
	return 0;
}

2、WaitForMultipleObjects

WaitForMultipleObjects函數是用來阻塞的,只有當線程狀態發生改變或者是等待時間到了,代碼才會繼續往下執行,否則就會處於阻塞狀態

WaitForMultipleObjects有四個參數如下

  • 等幾個內核對象
  • 等的內核對象句柄
  • 是否等內核對象全部狀態發生變化(TRUE是等待全部內核對象狀態發生改變,FALSE是有一個就行)
  • 等待時間
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{

	int* p = (int*)lpParameter;
	for(int i=0;i<*p;i++)
		{
			Sleep(50);
			printf("++++%d\n",i);
		}
	return 0;

}

int main(int argc, char* argv[])
{

	HANDLE ArrhThread[2];
	int n = 100;
	ArrhThread[0] = CreateThread(NULL,0,ThreadProc,(LPVOID)&n,0,NULL);
	ArrhThread[1] = CreateThread(NULL,0,ThreadProc,(LPVOID)&n,0,NULL);
	WaitForMultipleObjects(2,ArrhThread,TRUE,INFINITE);
	printf("線程結束 ");
	CloseHandle(ArrhThread[0]);
	CloseHandle(ArrhThread[1]);
	getchar();
	return 0;
}

3、GetExitCodeThread

GetExitCodeThread獲取線程的返回值

參數:

  • 句柄
  • 返回參數
#include "stdafx.h"
#include <windows.h>


DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{

	int* p = (int*)lpParameter;
	for(int i=0;i<*p;i++)
		{
			Sleep(50);
			printf("++++%d\n",i);
		}
	return 0;

}

DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{

	int* p = (int*)lpParameter;
	for(int i=0;i<*p;i++)
		{
			Sleep(50);
			printf("++++%d\n",i);
		}
	return 1;

}


int main(int argc, char* argv[])
{

	HANDLE ArrhThread[2];
	int n = 100;
	
	DWORD dwResult1;
	DWORD dwResult2;

	ArrhThread[0] = CreateThread(NULL,0,ThreadProc1,(LPVOID)&n,0,NULL);
	ArrhThread[1] = CreateThread(NULL,0,ThreadProc2,(LPVOID)&n,0,NULL);
	WaitForMultipleObjects(2,ArrhThread,TRUE,INFINITE);
	GetExitCodeThread(ArrhThread[0],&dwResult1);
	GetExitCodeThread(ArrhThread[1],&dwResult2);
	
	printf("線程結束\n");
	CloseHandle(ArrhThread[0]);
	CloseHandle(ArrhThread[1]);

	printf("%d\n",dwResult1);
	printf("%d\n",dwResult2);
	getchar();
	return 0;
}

十、單核CPU程序的切換

單核執行程序,每次切換,都會將自己的運行情況(數據),存到結構體CONTEXT context中,其中有各個寄存器的值,當程序執行完再切回來時,再將結構體中的數據還原,繼續執行

十一、鎖

1、創建全局變量

CRITICAL_SECTION cs;

2、初始化全局變量

InitializeCriticalSection(&cs);

3、 實現臨界區

EnterCriticalSection(&cs);
//使用臨界資源
LeaveCriticalSection(&cs);

#include "stdafx.h"
#include "windows.h"
int ticket = 10000;
CRITICAL_SECTION cs;		//創建臨界區


DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
	int* x = (int*)lpParameter;




	while(ticket > 0)
	{
		
		EnterCriticalSection(&cs);//使用
		if(ticket > 0)
		{
			printf("還有%d張票,當前線程是%d\n",ticket,*x);
			ticket--;
			printf("賣出一張,還有%d張,當前線程是%d\n",ticket,*x);	
		}
	
		LeaveCriticalSection(&cs);//釋放
	}

	return 0;

}


int main(int argc, char* argv[])
{
	
	int x =0;
	int y =1;

	HANDLE ArrhThread[2];
	InitializeCriticalSection(&cs);//初始化臨界區

	ArrhThread[0] = CreateThread(NULL,0,ThreadProc,&x,0,NULL);
	ArrhThread[1] = CreateThread(NULL,0,ThreadProc,&y,0,NULL);
	WaitForMultipleObjects(2,ArrhThread,TRUE,INFINITE);
	printf("線程結束 ");
	CloseHandle(ArrhThread[0]);
	CloseHandle(ArrhThread[1]);
	getchar();
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM