多线程基础学习

来源:互联网 发布:c语言编写程序的步骤 编辑:程序博客网 时间:2024/05/23 07:23
1.什么是进程?
进程代表了操作系统上运行着的一个应用程序。进程拥有自己的程序块,拥有独立的资源和
数据,并且可被操作系统来调度。即使同一个程序,当被强制多次启动时,也会被安放到不
同的进程中单独运行,直观的理解就是资源管理器中可以发现同一个程序被打开了两次
注意:并不是每一个进程都会在windows自带的进程浏览器中显示的


2.什么是线程?
线程也被称为微进程或者轻量级进程,它的概念和进程十分相似,是一个可以被调度的单元
并且维护自己的堆栈和上下文环境。线程是附属于进程的,
一个进程 可以包含1个或者多个线程,并且同一个进程内的多个线程共享一块内存块和资源。
一个线程是一个操作系统可以调度的基本单元,同时他的调度受限于包含改线程的进程,也就是说
操作系统首先决定下一个执行的进程,进而才会丢的该进程内的线程


3.线程和进程的区别
线程和进程最大的区别在于隔离性问题,每个进程都被单独的隔离,用有自己的内存块,独占的资源及
运行数据,一个进程的崩溃不会影响到其它的进程,而进程间的交互也是相当困难的。
和进程不同,同一进程内的所有线程共享资源和内存块,并且一个线程可以访问,结束同一进程内的其它线程
总结:
进程:相互进程间单独隔离,独立的资源内存块,彼此间互不影响,但相互间的交互也是相当困难的
线程:一个进程中的所有线程共享资源和内存卡,并且一个线程可以访问和结束同一进程内的其他线程
例如:
进程代表正在运行的应用程序的实体,而一个进程中可包含1或者多个线程




4.多线程程序在操作系统里是并行执行的吗?
1.线程调度问题
早期都是单线程,如果一个程序小错误,那之后的所有程序阻塞,所以逐渐产生分时和进程,线程的概念


线程调度:多个线程受到操作的调度控制,以决定何时运行哪个线程。
指操作系统如何安排线程执行顺序的算法。按照常规的分类,线程调度可以分为抢占调度和非抢占调度


2.抢占式调度
指每一个线程都只有极少的运行时间(windows NT内核模式下这个不会超过20ms)而当时间用完时,该线程就会被强制暂停,
保存上下文并把运行权利交给下一个线程,这样调度的结果就是所有的线程都在被快速第地切换,使用者感觉所有的线程在并行运行


3.非抢占式调度
非抢占式调度是指某个线程在运行时不会被操作系统强制暂停,它可以持续地运行直至运行告一段落并主动地交出运行权
在这样的调度模式之下,线程的运行就完全是单队列的,并且可能产生恶意程序长期霸占运行权的情况

注意:现在很多操作系统,都同时采用抢占式和非抢占式模式。对于那些优先级相当高的线程,操作系统采用非抢占式来给予充分的时间运行
而对于普通的线程,则采用抢占式模式来快速切换执行。


4.线程的并行问题
在单cpu单核的系统架构之上,线程的并行运行完全是使用者的主观体检,事实上在任意一时刻只可能存在一个处于运行状态的线程。
但在多cpu多或多核的架构上,情况略有不同。多cpu多核的架构允许操作系统完全并行地运行两个或者多个无其他资源争用的线程
理论上这样的架构可以使运行性能整数倍的提高


注意:微软提出超线程技术,就是逻辑上模拟多cpu的技术,但实际上它们却共享物理处理器和缓存。超线程对性能的提高相当有限


回答问题:
在单cpu的计算机架构上,任何时候只可能存在一个运行的线程,操作系统通过快速的调度轮换使使用者感觉到多线程在同时执行。
而在多cpu的架构上,则可能存在完全并行运行的线程,这取决于线程之间是否争用了其它的资源


5.什么是纤程
纤程是windows操作系统中独有的概念,但对于.NET来说线程的概念十分重要。


1.纤程是由微软提出的,当初是为了用来方便地一直到其他操作系统上的应用程序。一个线程可以拥有0个或者多个纤程,
一个纤程可以视为一个轻量级的线程,它拥有自己的栈和上下文状态,但是纤程的调度由程序员编码控制的,当一个纤程所在的线程得到运行时,程序员需要
手动地决定运行哪一个纤程。事实上,windows操作系统内核是完全不了解纤程的存在,它只负责调度所有的线程,而纤程之所以成为操作系统的概念,是因为
微软操作系统提供了关于线程操作的win32函数,能够方便地帮助程序员进行线程编程

2.纤程和线程的区别
一个线程包含多个纤程,纤程和线程最大的区别在于,线程的调度受操作系统的管理,程序员没有必要也没有办法进行完全干涉。
在windows这样的非实时操作系统中,一个线程何时运行完全无法预知。但纤程却完全受控于程序本身,可以说纤程允许程序员对多任务进行完全
自定义的调度和控制,可见纤程带给程序非常的大的灵活性,当然,纤程程序的编写要求程序员有非常深厚的操作系统知识
如图展示了进程,线程,纤程的部分关系。


图1


3.纤程在.NET中的地位
.NET运行框架没有做出关于线程真实性的保证,也就是说,程序员在.NET程序中新建的线程,并不一定会在操作系统层面上产生一个真正的线程
在.NET框架寄宿的情况下,一个程序员中的线程很有可能对应某个纤程,总之微软公司在线程的操作上为将来的产品留有余地,程序员应该清楚的意识到这一点
,从而避免错误的把.NET中的线程直接理解为操作系统层面的线程,事实上它可能是一个线程,一个纤程甚至与一个.NET自定义的结构,唯一可以确定的是,.NET
开发小组的设计会努力使程序的效率变高,所以程序员可以放心地区使用.NET的线程机制
如图2:


说明:所谓的CLR寄宿,是指CLR框架运行在某个应用程序而非操作系统内。常见的寄宿例子就是微软的SQL Server2005

总结:
纤程是微软公司提出的轻量级线程的概念,一个纤程可以拥有自己的栈和寄存器状态,一个线程可以包含多个纤程,和线程有操作系统调度有所不同的是
线程内纤程的调度完全有程序员自己控制,操作系统完全不知道纤程的存在。在.NET架构中,线程概念不一定和操作系统的线程相对应,在有些情况下.NET中的线程对应一个纤程



6. .NET中的多线程编程

1.如何在.NET程序中手动控制多线程
      .NET提供了多种实现多线程程序的方法,甚至在有些类型中的程序员可以完全无意识地享受到多线程带来的好处
(例如定时器类型)。但最直接且灵活性最大的,莫过于主动创建,运行,结束所有线程


所涉及的知识点:
System.Threading.Thread类型的使用
线程状态的概念
分析问题
1.编写多线程程序
.NET提供了非常直接的控制线程的类型:System.Threading.Thread类。
使用这个类型可以直观的创建,控制和结束线程,需要注意的是,程序员需要时刻知道程序
中的代码哪些属于这个线程,而哪些属于另外一个线程。
演示:一个简单的多线程程序

注意:生成一个Thread类型的对象并不意味着生成一个线程,事实上线程的生成是在调用Thread的start方法的时候
.NET小组没有说明这样的线程是否真正对应一个操作系统的线程



2.控制线程的状态
对于多线程程序来说,建立并启动一个线程,随后让其自动的完成工作是远远不够的,很多时候
程序员需要主动的关心线程当前所处的状态。在任意时刻,.NET中的线程都会处于一个下列状态集合中的某一个状态上:
Unstarted:线程建立,但未启动
Running:线程运行
WaitSleepJoin:线程休眠
SuspendRequested:已申请挂起
Suspended:线程挂起
AbortRequested:已申请中止
Stopped:线程中止
Thread类型提供了丰富的方法来让程序员查看并控制一个线程的状态,在具体了解这些方法如何使用之前,先宏观地看一下下一个线程是如何在状态之间转换的
下图展示了一个线程可能经过的状态转换:


Thread.Suspend和Thread.Resume被废弃,2.0以下版本就废弃了,原因是容易出现死锁问题


答案:.NET提供了System.Threading.Thread类型的封装了线程的操作,同过类型,程序员可以手动地创建,查询,控制以及结束线程


7.如何使用.NET的线程池
线程池的概念在很多框架下都有应用,.NET框架也不例外。.NET框架为程序员提供了线程池机制,
并且提供了方便的方法接口以供使用。熟练掌握线程池的用法。是程序员开发多线程程序必备的技能


涉及知识点:
.NET线程池的概念
.如何使用线程池


分析问题:
1.什么是.NET中的线程池
由于线程的创建和销毁需要非常大的性能开销,在window NT内核的操作系统上,每一个进程都会包含一个线程池
所谓的.NET线程池,是指由CLR管理的线程池,并不是指线程池是有.NET框架引用的,线程池相当于缓存的概念,在池中已经存在
了一些没被销毁的线程,而当应用程序需要一个新的线程时,就可以从线程池中直接获取一个已经存在的线程,相当于当一个线程被使用完毕后,并不会被立即销毁
而是放入线程池中等待下一次使用
CLR的线程池管理代码负责







原创粉丝点击