线程

一、什么是线程?

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;
}
posted @ 2021-12-16 18:36  lnterpreter  阅读(561)  评论(0编辑  收藏  举报