创建线程
第一个问题:什么是线程?
给出定义:线程是附属在进程上的执行实体,是代码的执行流程。(进程是资源,线程就是使用资源的人)
创建线程的函数:
CreateThread函数原型:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD
SIZE_T dwStackSize, //线程的堆栈大小(不填会给个默认的值)
LPTHREAD_START_ROUTINE lpStartAddress,//线程所需要执行的代码位置
LPVOID lpParameter,//线程参数 (其实就是代码的参数)
DWORD dwCreationFlags,//创建标志(可以选择挂起)(挂起可见上篇文章“进程”)
LPDWORD lpThreadId//threadidentifier(out)线程ID
)
线程控制
让线程停下来的函数
- 让自己停下来 Sleep()
- 让别人停下来 SuspendThread()
- 线程恢复 ResumeThread()
等待线程的函数
- 等待一个线程 WaitForSingleObject()
- 等待多个线程 WaitForMultipleObjects()
- 获取线程的执行结果 GetExitCodeThread()
线程上下文:其实就是储存线程所有寄存器的值的结构体。
设置、获取线程上下文(需要将线程挂起)
- GetThreadContext()
- SetThreadContext()
所有函数的参数 自己查手册吧… 太多了。
临界区
临界资源:指一次只能被一个线程访问的资源。
临界区:指访问临界资源的代码。
在某些程序中,需要多线程访问同一资源(如:多人购票,票便可以看作临界资源,而人通过界面执行代码进行买票,当票不多而购票人数多,多线程同时运行进行购票判断(判断是否有票),而程序还来不及更改总票数,此时就会出现没有票却能购到票的情况)
所以我们需要控制访问资源的线程数
线程锁:利用win32API函数,使得一段代码不能同时被多个线程执行
将要“锁住”的代码(如判断是否有票的程序)写在最后两个函数之间。
互斥体
函数原型:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTE SlpMutexAttributes, // 指向安全属性的指针
BOOL bInitialOwner, // 初始化互斥对象的所有者(就是互斥体的状态)
LPCTSTR lpName // 指向互斥对象名的指针
); 当此函数重复创建同名互斥体时,会返回第一个互斥体的句柄,
并且GetLastError()里会有东西......(运用这一原理可以防止程序多开)
互斥体也是内核对象。 目前阶段 将互斥体简单理解为令牌
当BOOL bInitialOwner=TURE时 互斥体无信号但当前线程是其拥有者
BOOL bInitialOwner=FALSE时,互斥体有信号
互斥体要配合两个API函数
- WaitForSingleObject() 当互斥体有信号或执行的线程是互斥体的拥有者时 可以获取令牌 获取令牌后函数会将信号置无
- ReleaseMutex() 释放令牌
将代码写在两个函数之间
互斥体与线程锁
乍一看,尼玛,这两个不一样吗?这功能明明一样啊
其实不然,好尼玛正经啊…
- 互斥体是一个内核对象,当你在一个线程中创建一个互斥体时,其他线程也可以访问此互斥体,由此可以实现不同进程不同线程对同一资源的访问控制。
- 互斥体可以设置等待时间
- 当程序在临界区里意外终止时,程序会进入无限的等待,而互斥体不会
- 但互斥体效率低于线程锁
事件
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,// 安全属性
BOOL bManualReset,// (通知类型TURE)(否则FALSE)
BOOL bInitialState,// 初始状态 (和互斥体一样 有无信号的意思)
LPCTSTR lpName // 指向对象名的指针 (如果其他进程不要用,可以不起名)
);
通知:当事件设为通知时,使用WaitForSingleObject()时函数不会将其信号置无。
事件可以实现一个功能叫线程同步。
线程同步:线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。(可以说是有序的互斥,你来一下我来一下的那种感觉)
要实现线程同步需要
- 创建两个事件
- 配合WaitForSingleObject()与SetEvent()
- 在两段不同的要被线程执行的代码块中SetEvent()另一代码块中的事件。SetEvent()会直接将本线程挂起并将另一事件置为有信号
我感觉这个讲法有问题,但目前只能这么浅显的理解了