线程和进程的概念

线程线程,进程进程,到底什么是线程,什么是熟练多线程编程?

今天来和大家一起讨论讨论线程基础,让大家知道线程的基本构造。

说线程之前,先要了解下进程,这个可不能不知道。

什么是进程?

  Microsoft设计操作系统内核时,他们决定在一个进程中运行应用程序的每一个实例,进程也不过就是个应用程序实例要使用资源的集合。(见过烤玉米,烤甘蔗的没?如下图:)

               

进程概念

    一个进程就好比一个烤筒,一个进程与其他进程互不干涉。操作系统为他们设立了一个虚拟地址空间,确保一个进程使用的代码和数据无法由另一个进程访问。这就保证了一个应用程序的健壮性。

    现在问题又来了,当一个进程进入无限循环了会怎么样?

    也就是程序没反应了,无限占用CUP,使CPU不能执行其他任何东西了,所以,进程是健壮(因为不会被破坏,而且也很安全),但还是会引起系统停止响应,也就是我们常说的“死机”。

    这时,Microsoft拿出的解决方案就是线程。也就是说,线程运行于进程之中。


线程概念

讲到线程,先来看看什么是线程:

  1. 线程内核对象, Windows为应用程序所创建的每个线程都有一个线程内核对象,这个对象包含一组对线程进行描述的属性,除此之外,还包含一个线程上下文(thread context),这个上下文是一个内存块,这个内存块用来包含CPU的寄存器集合(什么?你不知道CUP寄存器?火速去百度)。

  2. 线程环境块,包含一个内存块和一个异常处理链,还有些本地存储数据,GDI图形使用的一些数据结构。个人感觉没啥用,知道有就行。

  3. 用户模式栈,用来用户的操作带来的局部变量和实参,好比函数,程序执行到Add(i),那么它在执行函数之前会存下进入函数的地址,然后等函数调用完成之后再返回先前记录的地址,然后执行下一步。这个用户模式栈也就这用,要知道的是,Windows最少要为它分配1MB内存。

  4. 内核模式栈,在用户模式栈传递实参使会用到内核模式栈,调试大家都用过吧?  在调试程序的时候,是不是不能修改代码了?关键就在这,你执行程序之后,用户模式栈不能访问内核栈,你写的代码都送去内核了。

  5. DLL线程连接和线程分离通知,用过引用吧?这东西就是你在调用外部程序时需要提前引用一下的原因。加载这个程序,需要用到引用,正如没有引用,你程序就会出错。

现在来看看,大家熟悉的任务管理器,对线程来个形象的了解:

看到进程了? 看到线程了?

    1个线程占用1MB  , 1264个线程就占用1264MB。我就开了个VS   和SQL  两个大程序。程序开的不多。

再看看每个进程的线程数:

线程数也看到了,SQL-46个线程,最高内存使用。

    再来说说 经常遇到的情景,假设你正在玩一个大型游戏,突然老师来了,你要装作你正在干活,然后Tab+Alt,然后屏幕一黑,急了,怎么还没跳过去!!快点啊!!

o(∩_∩)o

现在来说说,一个Alt+Tab,Windows做了哪些事。

 

Windows之所以能快速接收我们的操作,我们觉得是时时在接收我们的输入,其实,在你不输入的时候,此线程已经提前终止此线程,而你的输入,唤醒文本输入线程只需要5毫秒。

并且这中间还存在一个叫上下文切换的东西,它的切换速度30毫秒,在Windows没有操作响应的时候,它做的切换工作超乎你的想象,因为有这个功能,保证了Windows的健壮性、快速反应等。

上下文切换,不是看不到的,回到那个情景,Alt+Tab,我们现在都知道它是在执行一个不同的线程,在你切换到桌面的时候,

游戏的线程代码和数据还在CUP的高速缓存当中(高速缓存能使CPU不需要经常访问内存,它访问缓存的速度比内存快得多),你的操作使CPU需要访问新的数据代码,而这些代码在内存中,

所以CPU又要重新读内存,重新填充告诉缓存,以恢复高速执行状态。

    好了现在我们知道Alt+Tab发生了什么事了。上下文切换所需时间,取决于CPU架构和速度,填充缓存取决于应用程序大小和CPU缓存大小等原因。

 

以上如有有理解错误的地方,请大家提醒指正,谢谢。


果糖网