zoukankan      html  css  js  c++  java
  • 并发编程(进程与线程)

    一、前言

    进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。

    进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展开的。   

    PS:即使可以利用的cpu只有一个(早期的计算机确实如此),也能保证支持(伪)并发的能力。将一个单独的cpu变成多个虚拟的cpu(多道技术:时间多路复用和空间多路复用+硬件上支持隔离),没有进程的抽象,现代计算机将不复存在。

     操作系统的作用:
        1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口
        2:管理、调度进程,并且将多个进程对硬件的竞争变得有序

    二、并发编程之多进程       

    多进程详细链接

     1. 什么是进程

        进程就是一个正在进行/运行的程序,换言之,进程指的是一个程序的运行过程
    
        程序vs进程:
            程序:只是一堆代码文件
            进程:程序运行的过程才是进程
    
        串行:一个任务完完整整地运行完毕,再执行下一个任务,按次序依次进行
            串行看起来就是一个一个运行的:对
            一个一个的运行就是串行:错误
    
        并发(切换+保存状态):多个任务看起来是同时运行,单核就可以实行并发
        并行:多个任务是真正意义上的同时运行,只有多核才能实现并行
    
        多道技术的产生背景:就是想要在单核下实现并发
       ps:
          现在的主机一般是多核,那么每个核都会利用多道技术
          有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个
          cpu中的任意一个,具体由操作系统调度算法决定
            如何实现:
                  1. 空间上的复用:将内存分为几部分,每个部分放入一个程序的数据,
             这样,同一时间内存中就有了多道程序的数据,为cpu在多个任务间切换做准备

           2. 时间上的复用:多个进程共享cpu的时间 关键点就是cpu在多个任务之间进行切换 有两种情况下会发生切换: 1. 一个任务占用cpu时间过长(没有遇到IO操作):会降低效率 1. 一个任务在运行的过程中遇到IO操作: 可以提升效率 2. 为何要用进程 要实现并发效果

         

    同步异步 and 阻塞非阻塞(重点)

    同步

    同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回。按照这个定义,其实绝大多数函数都是同步调用。但是一般而言,我们在说同步、异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。
    举例:
      1. concurrent.futures.ProcessPoolExecutor().submit(func,).result()
    2. concurrent.futures.ThreadPoolExecutor().submit(func,).result() 一提交便得到结果

    异步

    异步的概念和同步相对。当一个异步功能调用发出后,调用者不能立刻得到结果。当该异步功能完成后,通过状态、通知或回调来通知调用者。如果异步功能用状态来通知,那么调用者就需要每隔一定时间检查一次,效率就很低(有些初学多线程编程的人,总喜欢用一个循环去检查某个变量的值,这其实是一 种很严重的错误)。如果是使用通知的方式,效率则很高,因为异步功能几乎不需要做额外的操作。至于回调函数,其实和通知没太多区别。
    举例:
      1. concurrent.futures.ProcessPoolExecutor(3).submit(func,)
    2. concurrent.futures.ThreadPoolExecutor(3).submit(func,)

     阻塞

    #阻塞调用是指调用结果返回之前,当前线程会被挂起(如遇到io操作)。函数只有在得到结果之后才会将阻塞的线程激活。有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。
    #举例:
    #1. 同步调用:apply一个累计1亿次的任务,该调用会一直等待,直到任务返回结果为止,但并未阻塞住(即便是被抢走cpu的执行权限,那也是处于就绪态);
    #2. 阻塞调用:当socket工作在阻塞模式的时候,如果没有数据的情况下调用recv函数,则当前线程就会被挂起,直到有数据为止。

    非阻塞

    #非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前线程。

    总结

    1. 同步与异步针对的是函数/任务的调用方式:同步就是当一个进程发起一个函数(任务)调用的时候,一直等到函数(任务)完成,而进程继续处于激活状态。而异步情况下是当一个进程发起一个函数(任务)调用的时候,不会等函数返回,而是继续往下执行当,函数返回的时候通过状态、通知、事件等方式通知进程任务完成。
    
    2. 阻塞与非阻塞针对的是进程或线程:阻塞是当请求不能满足的时候就将进程挂起,而非阻塞则不会阻塞当前进程

    三、并发编程之多线程

    多线程详细链接

    1、什么是线程

    线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程

    关系:

    程序------>进程(至少一个主进程)------>线程(至少一个主线程,依赖于进程)

    进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

    #可以想象成北京地铁与上海地铁是不同的进程,而北京地铁里的13号线是一个线程,北京地铁所有的线路共享北京地铁所有的资源,比如所有的乘客可以被所有线路拉。
    生活中进程、线程

    2、创建线程的开销小

    如果我们的软件是一个工厂,该工厂有多条流水线,流水线工作需要电源,电源只有一个即cpu(单核cpu)

    一个车间就是一个进程,一个车间至少一条流水线(一个进程至少一个线程)

    创建一个进程,就是创建一个车间(申请空间,在该空间内建至少一条流水线)

    而建线程,就只是在一个车间内造一条流水线,无需申请空间,所以创建开销小

    3、线程与进程的区别

    线程共享创建它的进程的地址空间                      程有自己的地址空间。

    线程可以直接访问进程的数据段                         程拥有父进程的数据段的自己的副本。

    线程可以直接与进程的其他线程通信                  程必须使用进程间通信来与兄弟进程通信。

    线程很容易创建                                               新程需要复制父进程。

    线程可以对同一进程的线程进行相当大的控制    程只能对子进程进行控制。

    对主线程的更改(取消、优先级更改等)可能会影响进程中其他线程的行为                对父程的更改不会影响子进程。

    4、为何多线程

    多线程指的是,在一个进程中开启多个线程

          1. 多线程共享一个进程的地址空间

          2. 线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用

          3. 若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。

      很形象的线程小故事

     

  • 相关阅读:
    JeePlus:代码生成器
    JeePlus:API工具
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
  • 原文地址:https://www.cnblogs.com/nixindecat/p/9663400.html
Copyright © 2011-2022 走看看