线程(VC_Win32)

进程还可以通过套接字进行通信


线程概述

组成

  • 内核对象   操作系统用它来对线程实施管理,内核对象也是系统用来存放线程统计信息的地方,但创建线程时,系统创建一个内核对象,该线程内核对象不是线程本身,而是操作系统用来管理线程的较小数据结构,可以将线程内核对象视为有关于线程的统计信息组成的一个小型数据结构
  • 线程栈   它用于维护线程在执行代码时需要的所有函数参数和局部变量

注意

  • 线程总是在某个进程环境中创建的,系统从进程的地址工具中分配内存,供线程的栈使用,新的线程运行的进程环境与创建线程的环境相同,因此,新线程可以访问进程的内核对象的所有句柄,进程中的所有内存和在这个相同进程中的所有线程的堆栈.这使得单个进程中的多个线程确实能非常容易的相互通信
  • 线程只有一个内核和一个堆栈,保留记录很少,因此所需要的内存也很少,由于线程需要的开销比较少,因此在编程中经常采用多线程来解决编程问题,而尽量避免创建新的进程

线程运行机制

操作系统为每个运行线程安排一定的CPU时间----时间片,系统通过一种循环的方式为线程提供时间片,线程在自己的时间内运行,因为时间相当短,多个线程频繁地发生切换,因此给用户的感觉就是好像多个线程同时运行一样,但是如果计算机有多个CPU,线程就能真正意义上的同时运行了

生命周期

在创建子线程的线程中要是该线程结束了生命周期子线程也会结束生命周期

优点

  • 每一个线程可以独立地完成一个任务.当该程序一直到多CPU的平台上时,其中的多个线程就可以真正并发进行地同时运行了
  • 相对于进程来说
    • 对进程创建来说,系统要分配进程很大的私有空间,当然它占用的资源也就很多,而对多线程程序来说,多个线程共享一个地址空间,所以占用资源较少
    • 进程间切换时,需要交换整个地址空间,而线程之间切换时候只是切换执行环境,因此效率更高

单线程与多线程的执行区别 

注意

多线程访问共享变量时要避免多个线程同时对共享变量进行操作


线程相关函数详解

[进程创建][互斥对象][事件对象][关键代码段/临界资源]

进程创建相关函数

[creathread][线程入口函数原型][Sleep][CloseHandle]

CreateThread线程创建函数
函数原型

HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);

参数说明

  • lpThreadAttributes   指向SECURITY_ATTRIBUTES结构体指针,这里可以传递NULL,让该线程使用默认的安全性.但是,如果希望所有的子进程能够继承该线程对象的句柄,就必须设定一个SECURITY_ATTRIBUTES结构体,将它的bInheritHandle成员初始化为TRUE
  • dwStackSize:  设置线程初始堆栈大小,即线程可以将多少空间用于自己的栈,以字节为单位,系统会将这个参数值四舍五入到最接近页面大小,当保留地址空间的一块区域时,系统要确保该区域的大小是系统页面的大小的整数倍(页面是系统管理内存时使用的的内存单位,不同CPU其页面大小不同)
  • lpStartAddress:   指向应用程序定义的LPTHREAD_START_ROUTINE类型的函数指针,这个函数将由新线程执行,表明新线程的起始地址
  • lpParameter:   对于main函数来说可以寄售命令行的参数.同样我们也可以通过这个参数给创建的新线程传递参数.参数的值可以是一个数值,也可以使一个指向其他信息的指针
  • dwCreationFlags:   设置用于控制线程创建的附加标记,它可以是两个值得其中一个
    • CREATE_SUSPENDED  线程创建后处于暂停状态,直到程序调用了ResumeThread函数位置)
    • 0  线程在创建后立即运行
  • lpThreadId:   这个参数是一个返回值,它指向一个变量,来接收线程ID,当创建一个线程时,系统会为该线程分配一个ID(在windows 2000和windows NT4下,可以为NULL,但在windows95 和 windows 98下此参数不能为NULL)

返回值

新建立的线程句柄

threadProName 线程入口函数

函数原型

DWORD WINAPI threadProName(LPVOID lpParameter);

参数说明

  • lpParamer:   为创建线程CreateThread函数中的lpParameter参数的值

Sleep 线程睡眠函数

函数原型

void Sleep(DWORD dwMilliseconds);

参数说明

  • dwMilliseconds 指定线程的睡眠时间,单位为毫秒

CloseHandle 关闭线程句柄

函数原型

BOOL CloseHandle(
HANDLE hObject // handle to object to close
);

参数说明

  • hObject 要关闭的句柄

返回值

操作成功时候返回非零值,操作失败返回0

用途说明

若想要子线程可以运行而主线程不执行操作①可以让主线程睡眠,②可以让主线程执行循环空操作,但是用这种方式的话,对于主线程来说主线程是可以运行的,并且它会占有一定的CPU时间,这样会影响到MultiThread程序的执行效率.
说明 CreateThread启动了一个线程,同时产生一个句柄让你好操纵这个线程,如果你不要用这个句柄了就CloseHandle关掉它.调用这个CloseHandle并不意味着结束线程,而是表示不关心此句柄的状态了,也就无法控制子进程的线程了.如果需要关心,可以在子进程结束后再CloseHandle,但一定得CloseHandle.
CloseHandle使指定的句柄无效,减少对象的句柄计数,进行对象保持检验.当对象的最后一个句柄关闭时,对象将从系统中删除.关闭一个线程句柄并 不会终止一个线程,要释放一个线程对象,必须terminate线程,然后关闭所有的线程句柄.用CloseHandle只能关闭由CreateFile 函数返回的句柄.用FindClose来关闭由FindFirstFile返回的句柄.

互斥对象相关函数

[CreateMutex][ReleaseMutex][WaitForSingleObject]

CreateMutex 创建或打开互斥对象

函数原型 

HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwer,
LPCTSTR lpName
);

参数说明

  • lpMutexAttributes:   一个指向LPSECURITY_ATTRIBUTES结构的指针,可以将该参数传递NULL值,让互斥对象使用默认的安全性
  • bInitialOwer:   BOOL类型,指定互斥对象初始的拥有者,如果该值为true,则创建这个互斥对象的线程获得该互斥对象的所有权;否则,该线程将不获得所创建的互斥对象的所有权
  • lpName:   指定互斥对象的名称,如果此参数为NULL,则创建一个匿名的互斥对象

返回值

如果调用成功,该函数将返回所创建的互斥对象的句柄.如果创建的是命名的互斥对象,并且在CreateMutex函数调用之前,该命名的互斥对象存在,那么该函数将返回ERROR_ALREADY_EXISTS.

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值