标签:ade 自带 查看 nbsp 替代 在线 后台 art 常用
线程也是有两部分组成的:
进程是线程的容器,如果进程中有一个以上的线程,这些线程将共享进程的地址空间,操作空间中的数据,执行相同的代码,对相同的数据操作,甚至内核对象句柄(因为它是依托进程而不是线程存在的)。
所以进程使用的系统资源比线程多的多,线程只需要一个内核对象和一个堆栈。既然线程比进程需要的开销少,因此始终都应该设法用增加线程来解决编程问题。当然这也不是一成不变的,应该懂得权衡利弊。
何时运行线程
前面的章节已经提到过,当进程被初始化时,系统就要为进程创建一个主线程,用以和CC++运行期库的启动代码一起运行,然后进入入口点函数,然后运行至入口点函数返回并CC++运行期库的启动代码调用ExitProcess为止。
每个计算机都有一个功能强大的资源,CPU。让它闲置起来是没有道理的,应该让它处于繁忙之中,执行各种各样的工作:
最重要的是,多线程可以简化用户界面。设计一个拥有多线程的应用程序,可以扩大应用程序的功能。每一个线程都被分配了一个cpu,因此如果计算机有多个CPU,就可以让所有cpu都处于繁忙状态。
不能创建线程的情况
多线程并发至少有一个问题:代码的重入,数据访问的冲突。
一般来说一个应用程序有一个用户界面线程用于创建所有窗口,以及一个GetMessage循环。其他的线程都是工作线程,比用户界面线程优先级要低。
编写第一个线程函数
主线程有对应的入口点,那么线程函数也有个入口函数,作为开始执行第一条代码的地方。和主线程一样,执行代码到结束就释放资源,线程内核对象的引用计数递减。
CreateThread函数
调用下面的WindowsAPI就可以创建一个线程:
上面的函数被调用的时候,系统创建一个内核对象,用来管理与线程相关的数据结构,和进程是类似的。系统从进程的地址空间中分配内存,给线程的堆栈使用。新线程的运行环境与创建线程的环境相同。这样使得同一个进程的多个线程之间的通信时相对方便的。
注意:CreateThread函数是Windows用来创建线程的函数。可是如果你在写CC++代码的话,就不应该使用它了,而是使用VisualC++的运行时函数_beginthreadex。如果不是VisualC++编译器,你的编译器供应商会提供CreateThread的替代函数。反正不能用CreateThread。
psa参数是指向SECURITY_ATTRIBUTES结果的指针,一般使用默认值。具体的用法请看第三章。
cbStack参数用于设置线程堆栈大小,可以用链接程序的/STACK:[reserve][.commit]开关控制这个值。reserve参数用来设定系统为线程堆栈保留的地址控件量,默认1MB;commit参数用于设定“应该承诺用于堆栈保留区的物理存储器的容量”,默认值是1页。这个参数即便传递了值,函数仍然会检查链接器已经设置的值,哪个大用哪个。如果把0传进来,就使用Stack开关中设置的值。无论如何,这个值应该有个上限,否则如果存在递归则有可能消耗完所有的资源。
pfnStartAddr和pvParam分别是入口地址和参数。
fdwCreate参数可以是0或者CREATE_SUSPEND。前者表示线程创建后立即调度,后者表示创建线程后先暂停运行。然而后者并不常用。
pdwThreadID参数用来存放线程ID。
终止线程的运行
线程如果终止
一旦线程不再运行,系统中就没有别的线程能够处理这个线程的句柄,而别的线程可以调用GetExitCodeThread来检查hThread标识的线程是否时间终止运行。如果是这样,就确定它的退出代码:
如果尚未终止运行,函数就返回STILL_ACTIVE标识符(定义为0x103),放进pdwExitCode。如果成功就返回TRUE。
线程的其他性质
SP和IP分别是参数和线程函数的入口!
如果调用CreateThread创建了一个内核对象,下面的事情就会发生:
一旦内核对象创建完成:
每个线程都有自己的一套CPU寄存器,成为线程的上下文,用以反映线程上次运行时寄存器的状态。这些寄存器保存在CONTEXT结构里,这个结构本身则保存在线程的内核对象中。
ESP和EIP是线程上下文中两个最重要的寄存器。
标签:ade 自带 查看 nbsp 替代 在线 后台 art 常用
原文地址:https://www.cnblogs.com/leoTsou/p/12362352.html