线程知识点

原创 2003年04月03日 08:53:00

线程的基础知识
1. 进程与线程有那些区别和联系?
l 每个进程至少需要一个线程。
l 进程由两部分构成:进程内核对象,地址空间。线程也由两部分组成:线程内核对象,操作系统用它来对线程实施管理。线程堆栈,用于维护线程在执行代码时需要的所有函数参数和局部变量。
l 进程是不活泼的。进程从来不执行任何东西,它只是线程的容器。线程总是在某个进程环境中创建的,而且它的整个寿命期都在该进程中。
l 如果在单进程环境中,有多个线程正在运行,那么这些线程将共享单个地址空间。这些线程能够执行相同的代码,对相同的数据进行操作。这些线程还能共享内核对象句柄,因为句柄表依赖于每个进程而不是每个线程存在。
l 进程使用的系统资源比线程多得多。实际上,线程只有一个内核对象和一个堆栈,保留的记录很少,因此需要很少的内存。因此始终都应该设法用增加线程来解决编程问题,避免创建新的进程。但是许多程序设计用多个进程来实现会更好些。
2. 如何使用_beginthreadex函数?
使用方法与CreateThread函数相同,只是调用参数类型需要转换。
3. 如何使用CreateThread函数?
当CreateThread被调用时,系统创建一个线程内核对象。该线程内核对象不是线程本身,而是操作系统用来管理线程的较小的数据结构。使用时应当注意在不需要对线程内核进行访问后调用CloseHandle函数关闭线程句柄。因为CreateThread函数中使用某些C/C++运行期库函数时会有内存泄漏,所以应当尽量避免使用。
参数 含义
lpThreadAttributes 如果传递NULL该线程使用默认安全属性。如果希望所有的子进程能够继承该线程对象的句柄,必须将它的bInheritHandle成员被初始化为TRUE。
dwStackSize 设定线程堆栈的地址空间。如果非0,函数将所有的存储器保留并分配给线程的堆栈。如果是0,CreateThread就保留一个区域,并且将链接程序嵌入.exe文件的/STACK链接程序开关信息指明的存储器容量分配给线程堆栈。
lpStartAddress 线程函数的地址。
lpParameter 传递给线程函数的参数。
dwCreationFlags 如果是0,线程创建后立即进行调度。如果是CREATE_SUSPENDED,系统对它进行初始化后暂停该线程的运行。
LpThreadId 用来存放系统分配给新线程的ID。
4. 如何终止线程的运行?
(1) 线程函数返回(最好使用这种方法)。
这是确保所有线程资源被正确地清除的唯一办法。
如果线程能够返回,就可以确保下列事项的实现:
•在线程函数中创建的所有C++对象均将通过它们的撤消函数正确地撤消。
•操作系统将正确地释放线程堆栈使用的内存。
•系统将线程的退出代码设置为线程函数的返回值。
•系统将递减线程内核对象的使用计数。
(2) 调用ExitThread函数(最好不要使用这种方法)。
该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源(如C++类对象)将不被撤消。
(3) 调用TerminateThread函数(应该避免使用这种方法)。
TerminateThread能撤消任何线程。线程的内核对象的使用计数也被递减。TerminateThread函数是异步运行的函数。如果要确切地知道该线程已经终止运行,必须调用WaitForSingleObject或者类似的函数。当使用返回或调用ExitThread的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用TerminateThread,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。
(4) 包含线程的进程终止运行(应该避免使用这种方法)。
由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。就像从每个剩余的线程调用TerminateThread一样。这意味着正确的应用程序清除没有发生,即C++对象撤消函数没有被调用,数据没有转至磁盘等等。
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用GetExitcodeThread来检查由hThread标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码。
5. 为什么不要使用_beginthread函数和_endthread函数?
与_beginthreadex函数相比参数少,限制多。无法创建暂停的线程,无法取得线程ID。_endthread函数无参数,线程退出代码必须为0。还有_endthread函数内部关闭了线程的句柄,一旦退出将不能正确访问线程句柄。
6. 如何对进程或线程的内核进行引用?
HANDLE GetCurrentProcess(  );
HANDLE GetCurrentThread(  );
这两个函数都能返回调用线程的进程的伪句柄或线程内核对象的伪句柄。伪句柄只能在当前的进程或线程中使用,在其它线程或进程将不能访问。函数并不在创建进程的句柄表中创建新句柄。调用这些函数对进程或线程内核对象的使用计数没有任何影响。如果调用CloseHandle,将伪句柄作为参数来传递,那么CloseHandle就会忽略该函数的调用并返回FALSE。
DWORD GetCurrentProcessId(  );
DWORD GetCurrentThreadId(  );
这两个函数使得线程能够查询它的进程的唯一ID或它自己的唯一ID。
7. 如何将伪句柄转换为实句柄?
HANDLE hProcessFalse = NULL;
HANDLE hProcessTrue = NULL;
HANDLE hThreadFalse = NULL;
HANDLE hThreadTrue = NULL;

hProcessFalse = GetCurrentProcess(  );
hThreadFalse = GetCurrentThread(  );
取得线程实句柄:
DuplicateHandle( hProcessFalse, hThreadFalse, hProcessFalse, &hThreadTrue, 0, FALSE, DUPLICATE_SAME_ACCESS );
取得进程实句柄:
DuplicateHandle( hProcessFalse, hProcessFalse, hProcessFalse, &hProcessTrue, 0, FALSE, DUPLICATE_SAME_ACCESS );
由于DuplicateHandle会递增特定对象的使用计数,因此当完成对复制对象句柄的使用时,应该将目标句柄传递给CloseHandle,从而递减对象的使用计数。
8. 在一个进程中可创建线程的最大数是得多少?
线程的最大数取决于该系统的可用虚拟内存的大小。默认每个线程最多可拥有至多1MB大小的栈的空间。所以,至多可创建2028个线程。如果减少默认堆栈的大小,则可以创建更多的线程。

JAVA中的线程知识点整理

  • 2011年11月30日 19:40
  • 21KB
  • 下载

linux进程、线程常用的几个基础知识点

1.      Fork会复制父进程所有资源,父子进程完全独立 2.       vfork不会复制所有的资源,父子进程共享地址空间,在子进程中队虚拟内存空间变量的修改其实也是对父进程中值的修改。同...

[ASP.NET MVC 大牛之路]03 - C#高级知识点概要(2) - 线程和并发

我也想过跳过C#高级知识点概要直接讲MVC,但经过前思后想,还是觉得有必要讲的。我希望通过自己的经验给大家一些指引,带着大家一起走上ASP.NET MVC大牛之路,少走弯路。同时也希望能和大家一起交流...

Java线程常用知识点

1.开启线程的方法 2.currentThread()方法       这个方法显示的是当前代码块是被哪一个线程在使用。...

来段代码提提神-那些无法回避的知识点之线程和进程之间关系,并发的选择!

先说下并发和并行吧?这点是初学者的痛点。 并发:一个接一个执行; 并行:多个一起执行; 这个基本知识点明白了;就需要知道一点线程和进程的关系了; 进程和线程的关系  (1)一个线程只能属于一...

线程,进程知识点回顾,总有你需要的(面试必备!)

进程:进程是一个具有独立功能的程序关于某个数据集合的一次运行活动,即“运行中的程序”。 线程:被称为“轻量级进程”,是程序执行流的最小单元。 一个进程可包括多个线程。一个线程不可独立存在,它必须是...

Linux进程与线程及其他知识点拾遗

0x00进程与线程的区别    进程和线程都是由父进程创建出来了,区别在于是否共享页表和页目录表。    进程是通过系统调用fork来创建的。使用全新的页表和页目录表,实行copy_on_write策...
  • jltxgcy
  • jltxgcy
  • 2017年07月08日 17:06
  • 444

与线程有关的知识点总结 java

一、java线程的创建与启动   1.定义线程     线程的定义分为两种,一种是继承Java.lang.Thread类,另一种是实现java.lang.Runnable接口。  2.实例化线程   ...

进程和线程--重磅推出--知识点梳理

【参考书籍】:《现代操作系统》 ps:堆栈由于历史的原因,有几个地方叫做堆栈,名称比较混乱:硬件中有一组寄存器称为堆栈,用来在中断发生的时候自动保存当前程序的状态信息(该操作由硬件自动完成);函数中有...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程知识点
举报原因:
原因补充:

(最多只允许输入30个字)