zoukankan      html  css  js  c++  java
  • java多线程上篇(一)

    操作系统与程序运行以及进程简介

    一、线程与操作系统

      操作系统是对计算机硬件资源的管理程序,是应用程序与计算机硬件交互的中间层,其本质仍旧是运行于硬件电路上的程序

      对计算机硬件来说不存在操作系统,只是处理器对指令的执行,不过操作系统是一个特殊一点的程序。 所以不管你用了多少技术,框架,模式,实现了怎么样的协议与功能,原理是什么,也只是人类意识层面上的内容,到底层只有指令。

      所以,运行于计算机之上的这一切都只是程序

      这些程序经过指定的步骤,从高级到低级,从人类可以理解到无法识别,最终转换为计算机可以识别的指令。

        

      我们编写的所有的源代码,最终都要转换成计算机系统可以识别的内容,而计算机系统包括硬件以及运行其上的系统软件。
      我们所有的编码,都是面向指定的语法,而这门语言本身,则是面向操作系统的,因为外部软件通常是不能直接操纵硬件资源,需要借助于操作系统。
      所以某种程度上可以这样认为,所有的源代码都是面向语言的,而语言本身面向操作系统。

                       

     (一)、什么是程序

      遵循某种语言的源代码经过编译、翻译等步骤转换后的一组计算机能识别和执行的指令,这就是程序。

      操作系统将程序的一次运行抽象为进程

      简言之,如果    你处理器)按照   菜谱程序)去    做菜执行程序),这个过程就叫做       下厨做饭进程

        

       还有一个概念是进程上下文,刚才说到现代系统还可以并发的执行多道程序,必然存在着CPU的切换,进程间的切换,也被称之为上下文切换。

      通俗比喻:
        如果只有一个厨房,你做菜做一半了,然后需要让出来厨房让别人做,你需要做什么?
        收拾好你的食材,记住你刚才食材放置的位置以及处理的进度,哪个菜洗过了?盐放过了么?。。。等等这些数据就是进程上下文,当别人撤出去之后,你需要将这些状态还原,这就是上下文切换。

    (二)、并发并行

      下面这幅图可以很好地解释并发与并行

            一个咖啡机两个队伍,就是并发;两个咖啡机,两个队伍,就是并行。

      并发 concurrent ,通过CPU调度算法,进行进程间的切换,也就是多任务执行,操作系统将CPU时间片分配给每个进程,给人并行处理的感觉
      并行  parallel,并行就是同时执行的意思,多个CPU或者多个机器同时执行一段处理逻辑,是真正的同时。

    (三)、多线程

      很久很久很久以前,操作系统以串行的方式运行,当正在执行的程序遇到阻塞操作,比如等待IO时,CPU空闲等待,极大地浪费了CPU。所以后来出现了多任务操作系统,可以对程序进行切换,当遇到阻塞操作时,CPU可以去执行另外的程序,提高了CPU的利用率。CPU的效率变高了,而不是程序的运行所需时间变少了
     
      对于线程也是如此,多线程技术相当于是应用程序内部的“多任务”

      单核CPU

        对于一个单CPU系统,对于多任务的实现就是并发,操作系统不断地进行着切换,将时间片分配给不同的程序,以看起来像多个程序是共同运行的。

        然而单核场景下,尽管多线程在有些场景下可以提高CPU的利用率,但是对于单CPU系统(单核)系统,在有些场景下,反而会降低整体性能。

      多核CPU

        随着技术的发展, 能够装载的核心数目越来越多。对于多核CPU,能够真正的做到在同一瞬时,执行多个线程,是真正的并行。

        所以很显然,这种场景对于真正的并行,不管你的程序任务是什么样子的,对于多线程程序,必然能够提高程序的执行速度。

    二、总结

      不管是进程还是线程,都是操作系统对于程序执行的抽象描述,是相关数据:寄存器状态、堆栈值等所有相关数据的集合。
      通过进程的相关信息的维护管理,操作系统保障多道程序可以顺利的切换执行;而对于多线程的应用程序,需要开发者对线程的数据等相关信息进行控制,以保证多线程间可以正确的运行。
      多线程共享进程资源,而有些资源是互斥的,并不能允许同时访问,比如对计数器+1,如果临界区代码可以同时访问,可能两个人同时过来,每个人同时从1开始执行加1操作,结果却是2,这显然是不正确的。
      多线程编程需要解决的核心就是互斥资源的访问以及如何高效的利用CPU。
      保障资源的互斥访问是为了保证程序的正确性,否则再快的程序也没有意义;如果编写的程序非常的不合理,逻辑不清晰,反而可能会带来性能问题,而不是提高效率。
      所以多线程相关的技术的确很复杂,而且非常容易出错,而且学习成本很高,但是,他终归是为了提高CPU的利用率的同时并且保障临界资源的正确访问。

    进行概念详解

      操作系统是程序与硬件交互的中间层,现代操作系统将程序的一次执行抽象为进程和线程的概念。
      进程作为资源分配的基本单位,线程作为执行的基本单位。
      进程和线程其实就是操作系统程序本身实现控制一个程序运行的数据项描述
      所有的程序都是面向语言进行开发的,而语言本身是面向操作系统的,线程是操作系统对程序一次运行的抽象

    (一)、进程

      道程序出现之后,程序需要并发的执行,计算机的资源是共享的,而不再是某一程序运行后独享

      所以不再是顺序的,而是间断的,也不再是封闭,也不再具有可重现性

        

      还是以做饭为例,当只有你一个人使用厨房时,你可以随便;但是当多个人共享时,如果你还把你自己切了一半的菜扔到那边,可能会被扔掉,可能会被用掉,当然也可能没事。
      为了解决程序并发执行的问题,进程的概念被抽象出来,其实就相当于“一个厨房使用规章”被制定出来
      所以说进程和线程就是操作系统用来管理维护一个程序的运行于切换而设计出来的一个概念,然后通过各种数据结构以及值等实现描绘出来。

    (1)程序实体

      一个程序的运行主要下面几个部分的数据

        1. 进程本身的信息(现在谁在用厨房?现在盆盆罐罐都被你放了什么?)

        2. 可执行的代码是哪些?(菜谱步骤是什么?)

        3. 程序运行所需要的数据是什么?(食材是什么?佐料又是什么?)

      程序段、数据段、PCB(Process Control Block)三部分构成了进程实体

             

     (2)进程特征 

      1动态性    2. 并发性     3. 独立性      4.异步性

           

     (二)进程状态

    (1)基本状态

       创建、就绪、执行、阻塞、终止

      其中核心是:就绪、执行、阻塞

    状态转变简介:
      进程创建后,会创建PCB,以及相关的必须信息,然后就进入就绪状态,等待CPU的调度,一旦CPU对该进程调度执行,也就是该进程获得了时间片,那么就会进行执行,当时间片用完之后,如果任务还没有结束,那么就需要继续等待。(比如你做饭需要5小时,然而每个人只允许2小时,如果2小时你做不完,你必须让别人先做,你重新排队来)

      如果一个正在执行的程序遇到了IO请求,这通常是比较耗时的,进程会进入阻塞状态,进入阻塞状态的进程一旦获得了想要的结果,比如IO完成,那么就再次进入就绪状态,等待CPU的临幸。

    (2)挂起状态

      有些系统中,还会有挂起状态,可能系统需要让正在执行的程序暂停下来,也可能是资源不足了,将某些不重要的进程暂停。
      挂起是更彻底的暂停,可以认为挂起是“暂时被淘汰出内存的进程”

               

      就绪状态挂起后称之为静态就绪阻塞状态挂起后称之为静态阻塞,挂起后的状态不能够直接转换到执行状态活动状态经过挂起转换为静止状态,静止状态经过激活转换为活动状态.

       比如资源不充足时,将一些不重要的进程暂时挂起,挂起是真正的暂停执行,是一种主动式的管理,阻塞则是被动的,挂起也意味着置换到外存中,而不是内存中。

       不管是活动阻塞还是活动就绪,他们都在内存中,具备了相关条件,IO完成或者获得CPU时间片,就可以进行执行。挂起(静止)状态,静止阻塞还是静止就绪,他们都是外存中,并不能够执行,他们还需要一个载入到内存的过程

       一个静止阻塞的状态就相当于在外存中等待一个事件的完成,事件完成后,进入静止就绪状态,他此时还是不会得到CPU的调度,激活后才有机会得到CPU临幸

    (3)终止状态的转换

      终止状态通常是从执行状态进行转换,一般情况下不管一个什么状态的线程,他只有被执行时,才会可能进入终止状态。但是,在某些系统中,父进程有权利终止一个子进程,所以说这种情况下,就可能从阻塞或者就绪直接转换为终止状态。

     (三)、PCB( process control block)进程控制块

       进程是对于程序执行的抽象描述,那么进程控制块,这个对进程的描述,就相当于进程的元数据,用于描述进程本身。

       所以说,他就是一个数据结构,记录了用于控制管理进程的各个数据项。

      PCB 中记录了操作系统所需的、用于描述进程的当前情况以及控制进程运行的全部信息。
      进程控制块的作用是使一个在多道程序环境下不能独立运行的程序(含数据),成为一个能独立运行的基本单位,一个能与其它进程并发执行的进程。
      或者说,OS是根据 PCB来对并发执行的进程进行控制和管理的

      可见,在进程的整个生命期中,系统总是通过 PCB对进程进行控制的,亦即,系统是根据进程的PCB而不是任何别的什么而感知到该进程的存在的。

      PCB是进程存在的惟一标志。

            

      进程控制块主要包括:
      • 进程标识符
      • 计算机状态
      • 进程调度信息
      • 进程控制信息

      为了能对它们加以有效的管理,应该用适当的方式将这些PCB组织起来。目前常用的组织方式有以下两种。

        

    (四)、进程掌控的三座大山

      进程作为操作系统对程序一次运行的抽象描述
      进程的基本信息相当于元数据,就好像表结构一样以及一些必备的数据结构
      对于进程的掌控主要有三座大山:

      进程控制、进程同步、进程通信

      进程控制:
        一个进程从无到有,需要创建,创建之后因为调度而运行,因为撤销而消亡,需要有人管理他们,进程基本信息比如PCB从哪里来?都需要有人去做,这部分工作被称为进程控制
      进程同步:
        多进程并发执行,必然可能会出现竟态,比如同时访问某个共享资源,一个打印机不能同时打印语文和数学,所以必须做好顺序的调度,这部分的工作被称之为进程同步
      进程通信:
        多进程并发运行,如何进行进程间的联系,如何传递数据?不同计算机中的两个进程又是如何进行数据交互?这部分工作被称之为进程通信

    (五)、总结

      进程作为操作系统对程序执行的抽象,那么就使用了足够多的数据项对进程进行描述,所有的信息都是为了进程的管理、维护、调度、切换等。

      进程看似复杂,原理也是如此,操作系统使用多个数据项(数据结构)对程序的执行进行描述,然后定义了一整套的操作逻辑与规则。 

      进程有状态信息,操作系统负责管理状态的切换,那么必然需要记录进程的状态信息,既然是轮流分配时间片,就好像去办理业务,排队等待一样,但是无数个场景下都有VIP的存在,进程也是,也有优先级的概念
      计算机的程序最终会转换为一条条的指令,每一条指令的执行都需要借助于程序计数器,程序计数器是用于存放下一条指令所在单元的地址的地方,所以想要知道并且记住程序执行的进度位置,还需要掌握程序计数器的值。
      想要更好地管理进程,那么必然还会有一些统计信息,比如某进程运行了多久等记录统计信息,这些重要的信息都保存在进程的PCB中,所以说PCB是进程概念的核心,有了PCB程序才有并发执行的能力,通常,通常情况下,创建进程指的就是创建PCB。

      简言之,操作系统对进程的抽象就是对于一组数据结构以及操作这些数据结构的规则逻辑的实现。

    感谢: https://www.cnblogs.com/noteless/p/10350112.html

  • 相关阅读:
    MongoDB Query 常用方法
    plsql中文乱码问题(显示问号)
    xtype的使用
    LinQ:list基础操作
    VMware Fusion自动切换分辨率
    C#截取字符串的方法小结
    HTML 编码
    AMQP(Advanced Message Queuing Protocol)
    rabibtMQ安装及集群配置linux
    今天是个开始
  • 原文地址:https://www.cnblogs.com/FondWang/p/11955654.html
Copyright © 2011-2022 走看看