写点什么

7.4 操作系统:计算机如何处理成百上千的并发请求?

用户头像
张荣召
关注
发布于: 2020 年 11 月 09 日

7.4 操作系统:计算机如何处理成百上千的并发请求?

1.程序运行时架构

 程序是静态的。

 程序运行起来后,被称作进程。

2.操作系统多任务运行环境

     计算机的核心数是有限的。但是,服务器可以同时处理数以百计甚至数以千计的并发用户请求。

     那么,计算机如何做到的?

  • 进程分时执行。     

3.进程的运行期状态

   运行:进程在 CPU 上运行,则称进程处于运行态。处于运行状态的进程数目<=CPU 数目。

   就绪:当一个进程获得了一切所有资源,除 CPU 外。只要得到 CPU 即可运行,

             则称此进程处于就绪状态,就绪状态有时候也被成为等待运行状态。

   阻塞:也成为等待或者睡眠状态,当一个进程正在等待某一事件发生(例如:等待 I/O 完成,等待锁...)

             而暂时停止运行,这时即使把 CPU 分配给进程,进程也无法运行,故称为进程处于阻塞状态。

4.进程 VS 线程

     不同进程轮流在 CPU 上执行,每次都要进程间切换 CPU,代价非常大=>服务器应用通常是单进程多线程。

     进程向操作系统申请内存空间,所有的线程共享着进程的内存地址空间。

     而每个线程也会拥有自己私有的内存地址范围,其他线程不能访问。

     

5.线程栈

    多个线程,执行相同的代码,却得到不同的结果,怎么做到的?

    void f(){

          int x=g(1);

          x++;//g 函数返回,当前堆栈顶部为 f 函数栈帧,在当前栈帧继续执行 f 函数的代码

    }

    int g(int x){ return x+1;}


6.Java Web 应用多线程运行时视图

     启动 JVM 命令: java org.apache.catalina.startup.Bootstrap "$@" start   --找到入口方法:main  

     物理服务器(安装 OS)=>操作系统=>OS 启动 JVM 进程=>JVM 启动 Web 容器=>运行应用程序 War 包

     1.进程和线程来源:Tomcat(startup.sh:java org.apache.catalina.startup.Bootstrap "$@" start) 

     1.1JVM 进程启动: java   启动 java 虚拟机(JVM)。 操作系统 OS 解析"java"命令,启动 JVM。

          JVM 启动后,加载入口类---Tomcat 提供的 Bootstrap 的 main 方法。

          JVM 从入口函数 main 方法开始执行。==>JVM 进程启动

    1.2Tomcat 启动多线程:启动 80 端口,监听 HTTP 请求;启动多个线程,等待端口连接。

       监听 HTTP 请求到达 80 端口后,Tomcat 分派一个线程处理该端口连接。

      Tomcat 解析 HTTP 请求数据成 Request 对象,Response 对象,Session 上下文等。主类初始化完成。

      主类初始化完成,调用应用程序的 Servlet 代码。

     ==>此时,Tomcat 已经启动了多个线程。每个请求进来,Tomcat 就会分配一个线程处理该用户请求。

                                            调用 doGet,doPost 等方法。

   1.3 多线程并行执行:

=>并发请求进来,Tomcat 分配多个线程同时处理请求,多个请求并发调用 doGet,doPost.

        =>多个线程如果要使用锁,就要在锁上等待。通常不会再 Servlet 里面加锁操作--避免资源竞争,避免阻塞。

   1.4Spring 框架:调用 spring 的 servlet,servlet 调用 controller 类。  

7.线程安全

         当某些代码修改内存堆(进程共享内存)里的数据的时候,如果有多个线程同时执行,就可能出现同时修改数据的情况。

         比如:++i. 两个线程同时对一个堆中的数据执行+1 操作,得到结果 1,但是期望结果 2.

                   ++i 符合操作(读取-操作-保存)

         多个线程同时修改 Student 对象,数据正确性无法保证。如何保证数据安全?线程安全?

8.临界区

         多个线程访问共享资源的这段代码被称为临界区。

         解决线程安全问题的主要方法是使用锁,将临界区的代码加锁,只有获得锁的线程才能执行临界区代码。


         lock.lock();//线程获得锁,创建临界区

         i++;//临界区代码,i 位于堆中。

         lock.unlock();//线程释放锁

9.阻塞导致高并发系统崩溃

         锁(I/O)会引起线程阻塞。阻塞导致线程既不能继续执行,也不能释放资源。进而导致资源耗尽。最终导致系统崩溃。


10.避免阻塞引起的崩溃

         限流:控制进入计算机的请求数,进而减少创建的线程数。架构层面控制。--某种程度的不可用。

         降级:关闭部分功能程序的执行,尽早释放线程。

         反应式:异步;无临界区(Actor 模型)


用户头像

张荣召

关注

还未添加个人签名 2018.05.02 加入

还未添加个人简介

评论

发布
暂无评论
7.4操作系统:计算机如何处理成百上千的并发请求?