线程、线程句柄、线程ID
句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?
为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。
句柄地址(稳定)→记载着对象在内存中的地址→对象在内存中的地址(不稳定)→实际对象
线程与线程句柄的关系:
句柄可以认为是系统对资源(如线程)的分配的一个编号。关闭这个编号,对于不同的资源,效果不尽相同。对于线程来说,关闭这个编号并不意味着终止线程,只是之后很难再操纵这个线程。
线程句柄与线程ID的区别:
CreateThread() API 用于创建线程。 API 返回同时线程句柄和线程标识符 (ID)。线程句柄有完全访问权创建线程对象。 运行线程时线程 ID 唯一标识线程在系统级别。
●ID是在Windows系统范围内唯一标示Thread的。
●Handle是用来操作Thread的,可以有多个,每个HANDLE可以有不同的操作权限,在不同进程OpenThread得到的值不一样。
●线程的ID是系统全局的,其HANDLE是进程局部的.
●此ID只在线程的生存期内有效。
●HANDLE是os和client之间用来操作进程和线程一个桥梁,os有一张维护HANDLE的表单,里面大概放置了 HANDLE的引用计数和有关的属性,HANDLE是os标识进程和线程的东西,但是用户也可以用这个来标识进程和线程,对其操作;而ID是os用来标识进程和线程的,并且是全局唯一的, 但用户可以通过这个ID获得进程线程的HANDLE,多次得到的HANDLE并不一定是一样的.HANDLE是内核对象,而ID好像不是,并没有专门创建ID的函数.
●ID是CreateThread时操作系统自动生成的。
●线程的句柄和id是不同的。
在windows系统中,线程的id是唯一对应的,也就是说,如果两个线程返回相同的id,则他们必然是同一线程,反之一定是不同的线程。而线程的句柄并不是线程的唯一标识,线程的句柄只是用来访问该线程的的一个32位值,尽管相同的句柄一定标识同一线程,但同一线程可能拥有两个打开的句柄,因此,不能用句柄来区分两个线程是否是同一线程。
线程终止运行时发生的操作
当线程终止运行时,会发生下列操作:
• 线程拥有的所有用户对象均被释放。在 Windows 中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。
• 线程的退出代码从 STILL_ACTIVE 改为传递给 ExitThread 或 TerminateThread 的代码。
• 线程内核对象的状态变为已通知。
• 如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。
• 线程内核对象的使用计数递减 1。
当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用 GetExitcodeThread 来检查由 hThread 标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码:
BOOL GetExitCodeThread(HANDLE hThread, PDOWRD pdwExitCode);
退出代码的值在 pdwExitCode 指向的 DWORD 中返回。如果调用 GetExitCodeThread 时线程尚未终止运行,该函数就用 STILL_ACTIVE 标识符(定义为 0x103)填入 DWORD。如果该函数运行成功,便返回 TRUE。
线程退出的时候内核对象就会被激发, WaitForSingleObject()为堵塞函数,等待线程的内核对象被激发。所以终止线程并释放句柄对象的顺序是:TerminateThread()-->WaitForSingleObject()-->CloseHandle().
线程、线程句柄、线程ID的生成和消失
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, &dwId);
//至此,新线程,线程句柄,线程ID产生
TerminateThread(hThread, 0);
//至此,线程ID,线程句柄都依然存在
WaitForSingleObject(hThread, INFINITE);
//至此,线程本身和线程ID消失
CloseHandle(hThread);
//至此,线程句柄消失
线程、线程句柄、线程ID的更多相关文章
- EPROCESS 进程/线程优先级 句柄表 GDT LDT 页表 《寒江独钓》内核学习笔记(2)
在学习笔记(1)中,我们学习了IRP的数据结构的相关知识,接下来我们继续来学习内核中很重要的另一批数据结构: EPROCESS/KPROCESS/PEB.把它们放到一起是因为这三个数据结构及其外延和w ...
- 线程的2个ID
我们知道进程ID是操作系统调度的最小单位,有时候根据业务的需要,我们会使用到多线程技术,当创建了多个线程时,也会有一个线程ID,那这个线程ID和进程ID有什么不一样吗? 其中,线程组的线程ID是属于N ...
- 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。如:ABCABCABC…… 依次递归
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...
- python启动线程查看线程的名称和id;python杀掉进程的方法
def cpu_app(): print("CPU") #启动一个线程t=threading.Thread(target=cpu_app,args=()) t.daemon = T ...
- IOS 线程处理 子线程
IOS 线程处理 子线程的启动与结束 技术交流新QQ群:414971585 IOS中,如果要在主线程中启动一个子线程,可以又两种方法: [NSThread detachNewThreadSelec ...
- Windows线程漫谈界面线程和工作者线程
每个系统都有线程,而线程的最重要的作用就是并行处理,提高软件的并发率.针对界面来说,还能提高界面的响应力. 线程分为界面线程和工作者线程,界面实际就是一个线程画出来的东西,这个线程维护一个“消息队列” ...
- C# 线程--第四线程实例
概述 在前面几节中和大家分享了线程的一些基础使用方法,本章结合之前的分享来编写一些日常开发中应用实例,和编写多线程时一些注意点.如大家有好的实例也欢迎分享.. 应用实例 应用:定时任务程序 场景:系统 ...
- C# 线程--第三线程池
概述 线程池有那些优点: 1.在多线程中线程池可以减少我们创建线程,并合理的复用线程池中的线程.因为在线程池中有线程的线程处于等待分配任务状态. 2.不必管理和维护生存周期短暂的线程,不用在创建时为其 ...
- Java并发——线程安全、线程同步、线程通信
线程安全 进程间"共享"对象 多个“写”线程同时访问对象. 例:Timer实例的num成员,即add()方法是用的次数.即Timer实例是资源对象. class TestSync ...
- 新建线程与UI线程间的通信
现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...
随机推荐
- mvc中使用jsonp进行跨域请求详细说明
在web开发中,如果你要在不同域下进行数据异步请求,会出现一个No ‘Access-Control-Allow-Origin’ header is present on the requested r ...
- 去除html页面中按钮在ios中的默认样式,去除select自带的小三角图标
btn{-webkit-appearance: none;} -webkit-appearance: none也能去掉select下拉列表后面自带的小三角
- Android常见开源解决方案
原文:http://m.pstatp.com/group/6348269082899497218/?iid=6036708044&app=news_article&tt_from=mo ...
- SQL Server 如何创建定时作业
在做SQL server 管理时,往往需要每日执行定时任务,但是如果每天都去人工执行,非常不方便,而且一般定时操作,都应该是在数据库压力不大时,一般是在夜间.所以我们需要创建定时作业来代替人工的执行定 ...
- C#--方法的参数类型
在C#中,方法的参数类型有四种: 值类型 引用类型 输出类型 数组型参数 值参数: 所谓值参数,就是利用值向方法传递参数时,编译程序给实参的值做一份拷贝,并将此拷贝传递给该方法,这样做的结果就是被调用 ...
- 使用 Nginx 来反向代理多个 NoderCMS
Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄罗斯访问量第二的R ...
- $().text() 和 $().html()
1:性能 stackflow:http://stackoverflow.com/questions/1910794/what-is-the-difference-between-jquery-text ...
- IE6~9的css hack写法
_color: red; /* ie6 */ *color: red; /* ie6/7 */ +color: red; /* ie6/7 */ color: red\0; /* ie8/9 */ c ...
- ECSTORE2.0 下载 (变量标签)
条目 用途 备注 coupon.mc.use_times 优惠券可用次数 - security.guest.enabled 是否支持非会员购物 - site.version version的最后修改时 ...
- Ubuntu pip 安装网络爬虫框架 scrapy 出现的错误
1.问题 File "/usr/bin/pip", line 9, in <module> load_entry_point('pip==1.5.4', 'co ...