Windows下的多线程
- 一.线程函数
- WaitForMultipleObjects
- 二.句柄
- 三.线程对象
- 四.线程同步之事件对象
-
- 1.创建事件对象
- 2.设置事件对象状态
- [3. 重置事件对象状态](#3. 重置事件对象状态)
- [4. 请求事件对象](#4. 请求事件对象)
- 五.线程间通信之关键代码段
一.线程函数
CreateThread
CreateThread 是一种微软在 Windows API 中提供了建立新的线程的函数,该函数在主线程的基础上创建一个新线程。线程终止运行后,线程对象仍然在系统中,必须通过CloseHandle 函数来关闭该线程对象。
cpp
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD
SIZE_T dwStackSize,//initialstacksize
LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction
LPVOID lpParameter,//threadargument
DWORD dwCreationFlags,//creationoption
LPDWORD lpThreadId//threadidentifier
)
第一个参数 lpThreadAttributes 表示线程内核对象的安全属性,一般传入NULL 表示使用默认设置。
第二个参数 dwStackSize 表示线程栈空间大小。传入 0 表示使用默认大小(1MB)。
第三个参数 lpStartAddress 表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
第四个参数 lpParameter 是传给线程函数的参数。
第五个参数 dwCreationFlags 指定额外的标志来控制线程的创建,为 0 表示线程创建之后立即就可以进行调度,如果为 CREATE_SUSPENDED 则表示线程创建后暂停运行,这样它就无法调度,直到调用 ResumeThread()。
第六个参数 lpThreadId 将返回线程的 ID 号,传入 NULL 表示不需要返回
该线程 ID 号
unsigned long _beginthreadex(
void *security, // 安全属性, 为 NULL 时表示默认安全性
unsigned stack_size, // 线程的堆栈大小, 一般默认为 0
unsigned(_stdcall *start_address)(void *), // 线程函数
void *argilist, // 线程函数的参数
unsigned initflag, // 新线程的初始状态,0 表示立即执行,//CREATE_SUSPENDED 表示创建之后挂起
unsigned *threaddr // 用来接收线程 ID
);
CloseHandle
函数来关闭该线程对象。
GetCurrentThreadId()
获取id
WaitForSingleObject
来等待一个内核对象变为已通知状态
WaitForSingleObject(
In HANDLE hHandle, //指明一个内核对象的句柄
In DWORD dwMilliseconds //等待时间
);
WaitForMultipleObjects
cpp
WINBASEAPI
DWORD
WINAPI
WaitForMultipleObjects(
_In_ DWORD nCount,//等待个数
_In_reads_(nCount) CONST HANDLE* lpHandles,//等待数组
_In_ BOOL bWaitAll,//是等待所有线程还说等待任意一个发出信号
_In_ DWORD dwMilliseconds//等待时间
);
二.句柄
调用创建内核对象的函数后,该函数会返回一个句柄,它标识了所创建的对象。它可以由进程的任何线程使用。
常见的内核对象 : 进程、线程、文件,存取符号对象、事件对象、文件对象、作业对象、互斥对象、管道对象、等待计时器对象,邮件槽对象,信号对象
内核对象:为了管理线程/文件等资源而由操作系统创建的数据块。
三.线程对象
1.互斥对象(mutex)属于内核对象,它能够确保线程拥有对单个资源的互斥访问
权。
2.互斥对象包含一个使用数量,一个线程 ID 和一个计数器。其中线程 ID 用于
标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的
次数。
3.创建互斥对象:调用函数 CreateMutex。调用成功,该函数返回所创建的互斥
对象的句柄。
4.请求互斥对象所有权:调用函数 WaitForSingleObject 函数。线程必须主动请
求共享对象的所有权才能获得所有权。
5.释放指定互斥对象的所有权:调用 ReleaseMutex 函数。线程访问共享资源结
束后,线程要主动释放对互斥对象的所有权,使该对象处于已通知状态。
CreateMutex
cpp
HANDLE
WINAPI
CreateMutexW(
_In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,//指向安全属性
_In_ BOOL bInitialOwner,//初始化互斥对象的所有者 TRUE 立即拥有互斥体
_In_opt_ LPCWSTR lpName//指向互斥对象名的指针 L"Bingo"
);
加锁
cpp
WaitForSingleObject(
_In_ HANDLE hHandle,
_In_ DWORD dwMilliseconds
);
解锁
cpp
WINBASEAPI
BOOL
WINAPI
ReleaseMutex(
_In_ HANDLE hMutex
);
四.线程同步之事件对象
1.创建事件对象
调用 CreateEvent 函数创建或打开一个命名的或匿名的事件对象。
cpp
HANDLE
WINAPI
CreateEventW(
_In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,//安全属性
_In_ BOOL bManualReset,//复位方式 true是手动复原 false是自动还原为无型号
_In_ BOOL bInitialState,//初始状态 TRUE为有信号状态,FALSE为无型号状态
_In_opt_ LPCWSTR lpName//对象名称 null为无名的事件对象
);
2.设置事件对象状态
调用 SetEvent 函数把指定的事件对象设置为有信号状态。
3. 重置事件对象状态
调用 ResetEvent 函数把指定的事件对象设置为无信号状态。
4. 请求事件对象
线程通过调用 WaitForSingleObject 函数请求事件对象。