python之进程&线程理论

  • 什么是进程
    • 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
    • 在操作系统中,每启动一个应用程序其实就是OS开启了一个进程且为进程分类对应的内存/资源,应用程序的执行也就是进程在执行。
    • 狭义定义:一个正在运行的应用程序在操作系统中被视为一个进程
    • 举例: 我们有py1文件中和py2文件,两个文件运行起来后是两个进程。
  • 进程调度
    • 进程就是计算机中正在运行的一个程序或者软件,并且在上述工厂案例中,我们说单个CPU一次只能运行一个任务,那么你有没有在电脑上一边聊微信一边听音乐一边打游戏的场景啊?why?
      • 是因为CPU在交替运行多个进程。
    • 要想多个进程交替运行,操作系统必须对这些进程进行调度,这个调度也不是随机进行的,而是需要遵循一定的法则,由此就有了进程的调度算法。
      • 目前已实现的调度算法有:先来先服务(FCFS)调度算法、短作业优先调度算法和时间片轮转法。不过被公认的一种比较好的进程调度算法是"时间片轮转法"。
"时间片轮转法"调度算法的实施过程如下所述。
(1) os会创建多个就绪队列存储进程,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,以此类推。并且该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先级愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍
(2) 当一个新进程进入内存后,首先将它放入第一队列的末尾,排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地排队等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列。
(3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果os正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的服务,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。
  • 重要概念:并发与并行

    • 通过进程之间的调度,也就是进程之间的切换,我们用户感知到的好像是两个视频文件同时在播放,或者音乐和游戏同时在进行,那就让我们来看一下什么叫做并发和并行。
    • 无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真实干活的是cpu,而一个cpu同一时刻只能执行一个任务。
    • 并行:同时运行,只有具备多个cpu才能实现并行
    • 并发:是伪并行,即看起来是同时运行。
  • 线程

    • 线程是操作系统能够进行运算调度的最小单位(车间里的工人),它被包含在进程之中,线程是进程中的实际运作单位。一个进程中可以并发多个线程,每条线程并行执行不同的任务。
    • 注意:
      • 1.同一个进程内的多个线程是共享该进程的资源的,不同进程内的线程资源肯定是隔离的
      • 2.创建线程的开销比创建进程的开销要小的多
      • 3.每一个进程中至少会包含有一个线程,该线程叫做"主线程"
  • 思考:多线程可以实现并行吗?

    • 在CPU资源比较充足的时候,一个进程内的多线程,可以被分配到不同的CPU资源,这就是通过多线程实现并行。
    • 至于多线程实现的是并发还是并行?上面所说,所写多线程可能被分配到一个CPU内核中执行,也可能被分配到不同CPU执行,分配过程是操作系统所为,不可人为控制。所有,如果有人问我我所写的多线程是并发还是并行的?我会说,都有可能。
    • 不管并发还是并行,都提高了程序对CPU资源的利用率,最大限度地利用CPU资源
  • 线程的GIL锁

    • 首先,一些语言(java、c++、c)是支持同一个进程中的多个线程是可以应用多核CPU的,也就是我们会听到的现在4核8核这种多核CPU技术的厉害之处。
    • 那么我们之前说过应用多进程的时候如果有共享数据是不是会出现数据不安全的问题啊,就是多个进程同时一个文件中去抢这个数据,大家都把这个数据改了,但是还没来得及去更新到原来的文件中,就被其他进程也计算了,导致数据不安全的问题啊,所以我们是不是通过加锁可以解决啊,多线程大家想一下是不是一样的,并发执行也会有这个数据安全的问题。如何解决呢?
    • 但是python最早期的时候对于多线程也加锁,但是python比较极端的加了一个GIL全局解释锁,锁的是整个线程,而不是线程里面的某些数据操作,也就是说每次只能有一个线程使用cpu,也就说多线程用不了多核实现并行
    • 但是这个并不是python语言的问题,是CPython解释器的特性,在Cpython里面就是没办法用多核,这是python的弊病,历史问题,虽然众多python团队的大神在致力于改变这个情况,但是暂没有解决。
  • GIL介绍
    • 在同一个进程中只有一个线程可以获取cpu的使用权限,那么其他的线程就必须等待该线程的cpu使用权消失后才能使用cpu,即使多个线程直接不会相互影响,在同一个进程下也只有一个线程使用cpu,这样的机制称为全局解释器锁(GIL)。每一个 Python 线程,在 CPython 解释器中执行时,都会先锁住自己的线程,阻止别的线程执行。
    • GIL的优点:
      • 1、避免了大量的加锁解锁的繁琐操作
      • 2、使数据更加安全,解决多线程间的数据完整性和状态同步
    • 缺点:
      • 多核处理器的效果退化成单核处理器,只能并发不能并行
  • 总结:

    • 计算密集型任务使用多进程,因为可以享用多核的优势
    • io密集型任务使用多线程
posted @ 2022-04-30 23:20  Tony_xiao  阅读(37)  评论(0编辑  收藏  举报