• 第六篇:线程原理


    1、进程的分身术:线程

        线程是什么?进程是运转的程序。是为了在CPU上实现多道变成而发明的一个概念。但是进程在一个时间只能干一个事情。如果向同时干两件事,我们自然想到创说中的分身术。

        进程可以办到,办法就是进程。线程就是我们为了让一个进程同时干多件事情,而发明的分身术。

        既然线程就是进程的分身,那么每一个线程在本质上1是一致的,即同样同游程序文本。但由于是1分身,自然有不同地方1,这就是线程执行时的上下文不一致。事实上,我们说线程是进程里面的一个执行上下文或者执行序列。显然,一个进程可以同时拥有多个执行序列。这就像舞台,舞台上可以有多个演员同时登场,而这些演员和舞台就构成了一出戏。类比进程核1线程。每个演员是1一个线程,舞台是地址空间,这个同一地址空间里面的所有线程就构成了进程。

        在线程模式下,一个进程1至少有一个线程,但也可以由多个线程。

    麦库截图20171319135926344.jpg 

        将进程分解为线程还可以有效地利用多处理器和多核计算机。在没有线程的情况下,增加一个处理器并不能提高一个进程的执行速度。但如果分解为多个线程,则可以让不同的线程同时1运转在不同的处理器上,从而提高了进程的执行速度。

        例如我们使用1word时,实际上打开了多个线程,这些线程一个负责显示,一个接受输入,一个定时存盘,这些进程一起运转才能让我们感觉到,输入和显示同时发生,而不用输入一些字符,等待一会儿才显示到屏幕上。在我们不经意间,文字处理软件还能自动存盘。

    麦库截图20171419140429498.jpg 

    2、线程管理:

        有进城后,要管理进程。那么有线程后,也要进行管理。维持线程的各种信息。这些信息包含了线程的各种关键资料。存放这些信息的数据结构称为线程控制表或线程控制块。那么线程控制块里面到底包含哪些信息?

        我们说过线程共享一个进程空间,因此,许多资源是共享的。这些共享的资源显然不需要存放在线程控制模块里面,而是存放在线程控制块。但是由于线程是不同的执行序列,总会有些不能共享的资源。

    3、线程模型的实现:

        线程模型在进程基础上提供第二次并发。由于线程之间的共享远比进程之间的共享丰富,因此其在需要高度共享的环境1下发挥着重要作用。单线程这个模型如何实现?

        与进程一样,线程本身叶对应着某种物理现实,也需要存储和调度。在存储上,由于线程依附于进程而存在,其存储解决方案无需额外设计,而是直接赋予进程的存储方案。

        由于线程是在进程基础上产生的概念(进程里面的一个执行序列),其调度可以由进程负责。当然,我们也可以将线程的调度将给操作系统。而这两种不同的调度推手就形成了线程的两种实现:用户态和内核态实现。而进程自己管理就是用户态线程的实现,由操作系统管理就是内核态线程的实现。用户态和内核态的判断以线程表所处的位置为依据:位于内核叫内核态实现。用户态和内核态的判断以线程表所处的位置为依据:位于内核叫内核态实现,位于用户层就叫用户态实现。

        (1)内核态线程的实现:

        线程是进程的分身,是进程的不同执行序列。既然每一个线程是不同的执行序列,则说明线程应该是CPU调度的基本单位。我们知道CPU调度是由操作系统实现的。因此,让操作系统来管理线程似乎是天经地义的事情。

        那么操作系统是怎么来管理线程那?与管理进程一样,操作系统要管理线程,就要维护线程的各种资料,即将线程1控制块存放在操作系统内核空间。这样操作系统内核就同时保有进程控制块和进程控制块。

    麦库截图20171419143608613.jpg 

    由操作系统来管理线程有很多好处,最重要的好处是用户编程简单。因为现成的复杂性由操作系统承担,用户程序员在编程时无需管理线程的调度。即无需担心线程什么时候会执行,什么时候会挂起。另外一个重要的好处是,如果一个线程执行阻塞操作,操作系统就可以从容的调度另外一个线程执行。因为操作系统能监控所有的线程。

        (2)用户态线程的实现:

        就是用户自己做线程的切换,自己管理线程的信息,而操作系统无需知道线程的存在。

        那么1在用户态如何进行线程调度?那就是用户自己写一个执行系统,做调度器,即除了正常执行任务之外,还有一个专门负责线程调度的线程。由于大家都在用户态下执行,谁也不比谁占优势,要想取得CPU控制权只能靠大家自愿合作。一个线程在执行完一段时间之后1主动把资源释放给别人使用,而在内核态下则无需如此。

        那么用户态有什么优点?

        (1)灵活性,os无需知道线程的存在,在任何操作系统上都能使用;

        (2)线程切换快,切换在用户态进行,无需陷入到内核态。最后是不用修改操作系统,实现容易。

        麦库截图20171419144522985.jpg 

        缺点:程序变得诡异,用户态线程需要相互合作才能运转。这样,我们再写程序时,必须仔细斟酌在什么时候让出CPU给别的线程使用。

    3、现代操作系统线程实现1模型:

        先到操作系统将用户态和内核态线程模型相结合。用户态1的执行系统负责进程内部线程在非阻塞时的切换。内核态的操作系统负责阻塞线程的切换。即我们同时实现内核态和用户态线程管理。其中内核态线程数量较少,而用户态线程数量较多。每个内核态线程可以服务一个或多个用户态线程。用户态线程被多路复用到内核态线程上。

        例如:某个进程有5个线程,我们可以将5个线程分成2组,一组3个线程,另外一组2个线程。每一组线程使用一个内核线程。这样,该进程即将使用两个内核线程。如果一个线程阻塞,则与其同属于一族的线程皆被阻塞,但是另外一组线程却可以继续执行。

    麦库截图20171519155731245.jpg 

        这样,我们再分配线程时,我们可以将需要执行阻塞操作的线程设为内核态线程,而不会执行阻塞操作的线程设为用户态线程。

    4、多线程的关系:

        推出线程模型目的就是实现进程级并发。因为在一个进程中通常会出现多个线程,否则,我们也没有必要搞什么线程了。就像看舞台剧,如果从头到尾就一个人在演,我们就会觉得无聊。

        但共享一个舞台就会麻烦。就像人们共享资源时就会发生纷争。线程1在共享地址空间过程中也会产生矛盾。这些矛盾:有如下:

    (1)线程之间如何通信

    (2)线程之间如何同步

        而上述两个问题在进程层面也同样存在。从一个更高的层面上来看,不同的进程也共享着一个巨大的空间,这个空间就是整个计算机。因此进程之间也会存在矛盾,这些矛盾也体现在如何通信(沟通)和如何同步(协调)上。

    5、线程间同步

        引入进程之后,也引发了一个巨大的问题,即多线程程序的执行结果有可能是不确定的。而不确定则是我们1人类非常反感的东西。那么如何在保持线程这个概念的同时,消除其执行结果的不确定性?答案就是线程的同步。

        1、线程同步的目的:

        就是不管线程之间如何穿插,其运行结果都是正确的。或者说,要保证多线程执行下结果的正确性(确定性)而在达到这个目标的同时,要保持对线程执行的限制缺少越好。

        除此之外,线程同步的另外一个目的涉及执行效率。除了前面说过的多线程执行的结果是不确定的之外,其执行效率也是不确定的。比如在某段时间AA线程执行了3条指令,BB线程执行了5条指令。    线程a比线程b多执行了指令这不是关键。关键是到底线程        A是否比线程B执行的多,或者多多少》等皆是不确定的。如果我们想要确定就需要线程同步。

        线程同步:让所有线程按照一定的规则执行,使得其正确性和效率都有迹可循。线程同步的手段就是对线程之间的穿插进行控制。

        

        

        

  • 相关阅读:
    总结前端笔面试遇到的问题——HTML部分
    js中的克隆方法
    js操作cookie
    JS中4种常见的内存泄漏
    html、css、js三者的加载顺序
    js中object定义的几种方法
    关于settimeout的面试题
    css各种居中解决方法
    JS实现继承的几种方式
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/yjds/p/8597403.html
Copyright © 2020-2023  润新知