Win32 线程

本文详细介绍了Win32平台下线程的创建、挂起、恢复、终止及其判断方法,深入讨论了内核对象,包括线程切换、事件、互斥体、信号量等概念,强调了线程同步与互斥的重要性,同时对比了临界区与互斥体的使用和区别。
摘要由CSDN通过智能技术生成

进程是4GB,线程是EIP

一、线程控制

1.1 创建线程

 // 返回值:线程句柄

HANDLE CreateThread(				
  LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性 通常为NULL				
  SIZE_T dwStackSize,                       // 参数用于设定线程可以将多少地址空间用于它自己的堆栈				
				        					// 每个线程拥有它自己的堆栈
  LPTHREAD_START_ROUTINE lpStartAddress,    // 参数用于指明想要新线程执行的线程函数的地址				
  LPVOID lpParameter,                       // 线程函数的参数				
					 			            // 在线程启动执行时将该参数传递给线程函数
                            			    // 既可以是数字,也可以是指向包含其他信息的一个数据结构的指针
  DWORD dwCreationFlags,                    // 0 创建完毕立即调度  CREATE_SUSPENDED创建后挂起				
  LPDWORD lpThreadId                        // 线程ID 				
);				

1.1.1 线程句柄与线程ID

线程是由Windows内核负责创建与管理的,句柄相当于一个令牌,有了这个令牌就可以使用线程对象.

线程ID是身份证,唯一的,系统进行线程调度的时候要使用的.

1.1.2 创建线程

//创建一个新的线程				
HANDLE hThread = ::CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);			
				
//如果不在其他的地方引用它 关闭句柄
::CloseHandle(hThread);

1.1.3 线程函数

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
   
    return 结束码;
}

1.2 挂起线程

::SuspendThread(hThread);

1.3 恢复线程

::ResumeThread(hThread);	

1.4 终止线程

1.4.1 退出码

退出码,用于表示程序的执行状态,线程函数执行结束时返回的值。

1.4.2 方式一: ::ExitThread(dwExitCode)

说明:用于结束进程,在线程函数中同步调用,退出码为传入的dwExitCode参数的值。

特点:

  • 会把当前线程的整个堆栈释放(从线程开始跑分配的堆栈),但是一但使用此函数,由于整个堆栈被释放,你就没有机会做任何的东西了。
  • 而且在释放堆栈时不会管线程函数的堆中使用的空间,也就是或new的对象不会释放,需要手动delete

1.4.3 方式二:线程函数返回

说明:线程函数正常执行,执行完毕时通过return返回退出码,线程结束。

特点:

  • return前可以编写代码delete在线程函数中所new的对象,用法灵活。

1.4.4 方式三: ::TerminateThread(hThread, dwExitCode)

说明:用于结束进程,在线程函数外使用,异步调用

特点:

  • 在终止线程的同时会接着向下执行。不会清理指定线程的堆栈。

  • 需要通过::WaitForSingleObject(hThread,INFINITE);函数等待异步调用的结束,否则会在进程未结束时就向下执行。

1.5 判断线程是否结束

BOOL GetExitCodeThread(			
    HADLE hThread,			
    LPDWORD lpExitCode;			
);

返回BOOL值,用于判断线程是否结束,传入线程句柄退出码指针,如果线程结束,函数会将退出码存储到传入退出码指针所指向的地址。

二、内核对象

2.1 什么是内核对象?

在这里插入图片描述

内核对象:进程、线程、文件、文件映射、事件、互斥体等等

2.2 内核对象的通知状态

  1. 内核对象中的每种对象都可以说是处于已通知或未通知的状态之中

  2. 这种状态的切换是由Microsoft为每个对象建立的一套规则来决定的,在内核中就是个BOOL值

    • 已通知 TRUE
    • 未通知 FALSE
  3. 当线程正在运行的时候,线程内核对象处于未通知状态;
    当线程终止运行的时候,线程内核对象变为已通知状态

  4. 每种内核对象的通知状态对应不同的含义,会产生不同的结果(例如WaitForSingleObject()后回归未通知状态):

    重点 对于进程和线程,内核通知状态代表进程或线程是否正在执行,调用WaitForSingleObject()等待后,不会回归未通知状态。

2.3 内核对象的使用

2.3.1 事件内核的创建

// 创建事件内核
HANDLE g_hEvent = CreateEvent(NULL, TRUE, FALSE, "XYZ");

// 创建互斥体内核
HANDLE g_hMutex  = CreateMutex(NULL, FLASE, "XYZ");

2.3.2 事件内核的获取

// 获取事件内核
HANDLE g_hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "XYZ");

// 获取互斥体内核
HANDLE g_hMutex = OpenMutex(EVENT_ALL_ACCESS, FALSE, "XYZ");

2.4 内核对象的销毁

2.4.1 事件内核的销毁

关闭事件内核的句柄
CloseHandle(g_hEvent);
  1. 当没有其他程序引用时,系统会销毁内核对象(使用数量)。
  2. 内核对象的生命周期,可能比创建它的对象要长。

4.2.2 内核的生命周期(计数器)

每个内核对象都有一个计数器,记录着内核对象的使用情况。当内核对象中的计数器的值为 0 时,系统会销毁内核对象。

拿事件(Event)来举例:

  • 调用CreateEvent()OpenEvent()时,计数器+1
  • 调用CloseHandle(hEvent)时,对应事件的计数器 -1,当计数器回归0时,系统会销毁内核对象

2.5 WaitForSingleObject()函数

DWORD WaitForSingleObject(			
    HANDLE hHandle;					//handle to object
    DWORD dwMilliseconds			
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现win32线程的顺序执行,可以使用信号量机制和等待函数。具体的实现步骤如下: 1. 创建多个线程,并用一个数组来保存线程句柄。 2. 创建一个信号量,并初始化为0,表示开始时所有线程都需要等待。 3. 在每个线程的执行代码中,首先调用等待函数WaitForSingleObject来等待信号量。这会将线程阻塞,直到信号量变为非零。 4. 在某个线程的执行代码中,调用ReleaseSemaphore函数来将信号量的值加1,表示该线程已经执行完毕,可以让下一个线程开始执行。 5. 循环执行步骤3和步骤4,直到所有线程都执行完毕。 下面是一个简单的示例代码: ``` #include <Windows.h> #include <iostream> using namespace std; const int THREAD_NUM = 3; HANDLE g_hThread[THREAD_NUM]; HANDLE g_hSemaphore; DWORD WINAPI ThreadProc(LPVOID lpParam) { int nThreadID = (int)lpParam; cout << "Thread " << nThreadID << " is waiting." << endl; WaitForSingleObject(g_hSemaphore, INFINITE); cout << "Thread " << nThreadID << " is running." << endl; Sleep(1000); cout << "Thread " << nThreadID << " is done." << endl; ReleaseSemaphore(g_hSemaphore, 1, NULL); return 0; } int main() { g_hSemaphore = CreateSemaphore(NULL, 0, THREAD_NUM, NULL); for (int i = 0; i < THREAD_NUM; i++) { g_hThread[i] = CreateThread(NULL, 0, ThreadProc, (LPVOID)i, 0, NULL); } ReleaseSemaphore(g_hSemaphore, 1, NULL); WaitForMultipleObjects(THREAD_NUM, g_hThread, TRUE, INFINITE); CloseHandle(g_hSemaphore); for (int i = 0; i < THREAD_NUM; i++) { CloseHandle(g_hThread[i]); } return 0; } ``` 在这个示例代码中,我们创建了3个线程,并用一个数组保存了它们的句柄。我们还创建了一个信号量,初始值为0,表示所有线程都需要等待。在每个线程的执行代码中,首先调用等待函数WaitForSingleObject来等待信号量,然后执行一些耗时的操作,最后调用ReleaseSemaphore函数来释放信号量。在主函数中,我们先将信号量的值加1,表示第一个线程可以开始执行。然后调用WaitForMultipleObjects函数等待所有线程执行完毕。最后,释放资源并退出程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值