Windows的线程使用

Windows的线程使用

2019521

12:12

   

和Linux不同,Windows的线程在执行结束以后默认不需要进程中的函数来引导销毁,而是由操作系统来自动销毁内存空间。

   

内核对象

操作系统创建的资源(Resource)有很多种,进程,线程,文件,信号量,互斥量等。他们都有一个共同点,"都是由Windows操作系统创建并管理的资源"。

不同的资源类型在"管理"的方式上存在有差异。操作系统为了记录管理资源的相关信息,在其内部生成了数据块(结构体变量)。由于每种资源需要维护的信息不同,所以每种资源拥有的数据块格式也具有差异。这类数据称之位"内核对象"。

所以可以理解,"内核对象"就是Windows操作系统为了管理系统资源而创建的资源信息对象。

内核对象的所有者是内核(操作系统)。内核对象的创建、管理、销毁时机等工作都有操作系统来完成。

   

基于Windows的线程创建

现代操作系统都在系统级别上支持线程的运行。程序开始运行以后,调用main函数的主体是线程。main函数的运行基于线程来完成。进程承载线程的运行。

   

  • 非显式创建线程的程序(如select服务器端)可以描述符:单一线程模型的应用程序
  • 显示创建线程的程序可以描述为:多线程模型的应用程序

   

windows创建线程的函数

系统函数

#include <windows.h>

HANDLE CreateThread(

LPSECURITY_ATTRIBUTES lpThreadAttributes,

SIZE_T dwStackSize,

LPTHREAD_START_ROUTINE lpStartAddress,

LPVOID lpParameter,

DWORD dwCreateionFlags,

LPDWORD lpThreadID

);

->>成功时返回线程句柄,失败时返回NULL

   

lpThreadAttributes:线程安全相关信息,NULL为默认设置

dwStackSize:分配给线程的栈大小,传递0生成默认大小

lpStartAddress:线程的main函数

lpParameter:线程main函数的参数

dwCreationFlags:指定线程创建后的行为,传递0,线程创建后立即进入可执行状态

lpThreadld:用于保存线程ID的变量地址

   

标准函数

#include <process.h>

uintptr_t _beginthreadex(

void * security,

unsigned stack_size,

unsigned (* start_address)(void*),

void * arglist,

unsigned initflag,

unsigned * thrdaddr

);

->>成功时返回线程句柄,失败时返回0

   

如果线程需要使用C/C++标准函数,则需要通过使用_beginthreadex函数来创建线程。与CreateThread函数相比,参数意义及调用顺序都没有区别。只是数据类型有所差异,需要适量修改。

   

句柄、内核对象与ID间的关系:

  • 通过句柄区分内核对象
  • 内核对象拥有资源的相关信息(通过内核对象区分线程)
  • 线程ID用于区分操作系统创建的所有线程

   

内核对象的两种状态

资源类型不同,内核对象也含有不同的信息。其中,应用程序实现过程中需要特别关注的信息被赋予某种"状态(state)"。线程内核对象中需要重点关注线程是否已经终止。终止状态又称为"signaled状态",未终止状态称为"non-signaled状态"。

进程和线程的初始化状态时non-signaled状态。内核对象中带有一个boolean变量,其初始值为FALSE,当发生约定情况(进程/线程结束),该值变为TRUE,即为signaled状态。

   

验证signaled状态(线程结束)

#include <windows.h>

DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);

->>成功时返回时间信息,失败时返回WAIT_FAILED

hHandle:内核对象句柄

dwMilliseconds 毫秒为单位的等待时间,传递INFINITE阻塞

返回值:进入signaled状态返回WAIT_OBJECT_0,超时返回WAIT_TIMEOUT

   

该函数由于发生事件(signaled)返回时,有时会把相应内核对象再次变为non-signaled状态,具有这种特性的内核对象称为"auto-reset模式"的内核对象,而不会自动跳转的内核对象称为"manual-reset模式"的内核对象。

   

验证多个内核对象的signaled状态

#include <windows.h>

DWORD WaitForMUltipleObjects(

DWORD nCount, const HANDLE * lpHandles, BOLL bWaitAll,

DWORD dwMilliseconds);

->>成功时返回事件信息,失败时返回WAIT_FAILED

   

nCount:内核对象总数

lpHandles:内核对象句柄数组

bWaitAllTRUE,等待全部。FALSE,有一个就返回

dwMilliseconds:等待时间,毫秒为单位,传递INFINITE阻塞

原文地址:https://www.cnblogs.com/freesfu/p/10911693.html