在处理多线程程序之前,还是需要复习一些基础知识的。
进程简单来说,进程是一个运行的程序,用来描述一组资源(如外部代码库和主线程)和程序运行所必须的内存分配。对于每一个被加载到内存的*.exe,在他的生命周期中操作系统会为之创建一个单独且隔离的进程。
由于一个进程的失败不会影响其他进程,这种隔离的方式,运行库环境会更加健壮和稳定。
应用程序域在.net 平台下,可执行程序并没有直接加载在windows进程中,而传统的非托管程序是直接承载的。实际上,.net可执行程序承载在进程的一个逻辑分区中,术语叫应用程序域(APPDomain)。可见,一个进程可以包含多个应用程序域,这种对传统的windwos进程进一步分区具有以下几个好处:
应用程序域是.net 平台操作系统独立性的关键特性。这种逻辑分区将不同的操作系统表现加载可执行程序的差异抽象化了。
和进程相比,AppDomian的cpu和内存占用小得多。因此clr加载和卸载程序比起来完成的进程要快得多。
提供了深度隔离,如果进程中的一个应用程序域失败了,不会影响其他。
当一个程序集同时被多个应用程序域调用时,会出现两种情况:
第一种情况:CLR分别为不同的应用程序域加载此程序集。
第二种情况:CLR把此程序集加载到所有的应用程序域之外,并实现程序集共享,此情况比较特殊,被称作为Domain Neutral。
在应用程序域之间的数据时相互独立的,当需要在其他AppDomain当中执行当前AppDomain中的程序集代码时,可以使用CrossAppDomainDelegate委托。把CrocessAppDomainDelegate委托绑定方法以后,通过AppDomain的DoCallBack方法即可执行委托。
上下文应用程序域是进程中承载程序集的路基分区,在应用程序域当中,存在更细粒度的用于承载.Net对象的实体,用于承载.Net实体的东西就叫.Net上下文Context。
所有的.Net对象都存在于上下文当中,每个AppDomain当中至少存在一个默认上下文(context 0)。
一般不需要指定特定上下文的对象被称为上下文灵活对象(context-agile),建立此对象不需要特定的操作,只需要由CLR自行管理,一般这些对象都会被建立在默认上下文当中。
线程存在于进程当中,它在不同的时刻可以运行于多个不同的AppDomain当中。它是进程中的基本执行单元(由此可以理解web服务器的异步不能提高单次访问速度,但是可以提高服务器的吞吐量)
在进程入口执行的第一个线程被视为这个进程的主线程。在.Net应用程序中,都是以Main()方法作为入口的,当调用此方法时,系统就会自动创建一个主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。
总结进程(Process)、线程(Thread)、应用程序域(AppDomain)、上下文(Context)的关系如图5.0,一个进程内可以包括多个应用程序域,也有包括多个线程,线程也可以穿梭于多个应用程序域当中。但在同一个时刻,线程只会处于一个应用程序域内。线程也能穿梭于多个上下文当中,进行对象的调用。
虽然进程、应用程序域与上下文在平常的开发中并非经常用到,但深入地了解三者的关系,熟悉其操作方式对合理利用系统的资源,提高系统的效率是非常有意义的。