一、线程
线程是指进程内的一个执行单元,也是进程内的可调度实体;当进程启动的同时启动了一个线程,叫做主线程或者执行线程;一个进程可以有多个线程,每个线程都共享进程的地址空间,并且共享进程地址空间内的资源和各种数据;每个线程都占用CPU份额,也就是CPU的时间,线程就是数据在CPU上运行,是个动作。线程可以创建子线程。主线程退出,主线程下的所有子线程都失效,主线程所在进程也被系统撤销,地址空间也被释放。同一时刻,一个CPU不能运行两个线程。
二、事件
事件对象是最基本的内核对象;事件对象包含引用计数、事件类型、事件的通知状态等信息。主要分为两大类:人工重置对象和自动重置对象。人工重置对象可以同时有多个线程等待到时间对象,成为可调度线程;自动重置对象,等待该事件对象的多个线程只能有一个线程成为可调度线程。若为自动重置事件对象,当某一个线程等待到事件对象以后,系统自动将事件变为未通知状态。
三、函数介绍
HANDLE WINAPI CreateEvent(
__in LPSECURITY_ATTRIBUTES lpEventAttributes, //事件对象的安全属性,如果为Null不能被子进程继承If this parameter is NULL, the handle cannot be inherited by child processes
__in BOOL bManualReset,//事件对象的类型,TRUE表示人工重置事件对象,FLASE表示自动重置事件对象;
__in BOOL bInitialState,//事件初始状态 true通知状态;flase 未通知状态
__in LPCTSTR lpName//事件对象的名称If lpName is NULL, the event object is created without a name
);
BOOL SetEvent(
HANDLE hEvent
); //This function sets the state of the specified event object to signaled.设为有信号状态
BOOL ResetEvent( HANDLE hEvent ); //This function sets the state of the specified event object to nonsignaled.设为无信号状态
创建线程
HANDLE WINAPI CreateThread(
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,//指向安全属性的指针
__in SIZE_T dwStackSize,//初始线程栈的大小
__in LPTHREAD_START_ROUTINE lpStartAddress,//指向线程函数的指针
__in LPVOID lpParameter,//线程参数
__in DWORD dwCreationFlags,//创建标识If this value is zero, the thread runs immediately after creation.
__out LPDWORD lpThreadId//指向存放线程ID的指针
);
//Creates a thread to execute within the virtual address space of the calling process. 在调用进程的虚拟地址空间中创建一个线程来执行。
四、笔试题
编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推
// Multithreading.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdlib.h>
#include <Windows.h>
#include <iostream>
using namespace std;
HANDLE hEventA = INVALID_HANDLE_VALUE;
HANDLE hEventB = INVALID_HANDLE_VALUE;
HANDLE hEventC = INVALID_HANDLE_VALUE;
DWORD __stdcall ThreadA(LPVOID lparam)
{
DWORD dRet = TRUE;
int nNums = 0;
while(1)
{
WaitForSingleObject(hEventA,INFINITE);
ResetEvent(hEventA);
cout<<"A"<<endl;
nNums++;
SetEvent(hEventB);
//Sleep(10);
if (nNums == 10)
{
break;
}
}
return dRet;
}
DWORD __stdcall ThreadB(LPVOID lparam)
{
int nNums = 0;
DWORD dRet = TRUE;
while(1)
{
WaitForSingleObject(hEventB,INFINITE);
ResetEvent(hEventB);
//ResetEvent(hEventA);
cout<<"B"<<endl;
nNums++;
SetEvent(hEventC);
//Sleep(10);
if (nNums == 10)
{
break;
}
}
return dRet;
}
DWORD __stdcall ThreadC(LPVOID lparam)
{
int nNums = 0;
DWORD dRet = TRUE;
while(1)
{
WaitForSingleObject(hEventC,INFINITE);
ResetEvent(hEventC);
//ResetEvent(hEventB);
cout<<"C"<<endl;
nNums++;
SetEvent(hEventA);
//Sleep(10);
if (nNums == 10)
{
break;
}
}
return dRet;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a = sizeof(long);
hEventA = CreateEvent(NULL, true, true, L"eventa");
hEventB = CreateEvent(NULL, true, false, L"eventb");
hEventC = CreateEvent(NULL, true, false, L"eventc");
HANDLE hThreadA = INVALID_HANDLE_VALUE;
HANDLE hThreadB = INVALID_HANDLE_VALUE;
HANDLE hThreadC = INVALID_HANDLE_VALUE;
hThreadA = CreateThread(NULL, 0, ThreadA, NULL, 0, NULL);
hThreadB = CreateThread(NULL, 0, ThreadB, NULL, 0, NULL);
hThreadC = CreateThread(NULL, 0, ThreadC, NULL, 0, NULL);
system("pause");
if (NULL != hEventA)
{
CloseHandle(hEventA);
hEventA = INVALID_HANDLE_VALUE;
}
if (NULL != hEventB)
{
CloseHandle(hEventB);
hEventB = INVALID_HANDLE_VALUE;
}
if (NULL != hEventC)
{
CloseHandle(hEventC);
hEventC = INVALID_HANDLE_VALUE;
}
if (NULL != hThreadA)
{
CloseHandle(hThreadA);
hThreadA = INVALID_HANDLE_VALUE;
}
if (NULL != hThreadB)
{
CloseHandle(hThreadB);
hThreadB = INVALID_HANDLE_VALUE;
}
if (NULL != hThreadC)
{
CloseHandle(hThreadC);
hThreadC = INVALID_HANDLE_VALUE;
}
return 0;
}