【Python面试场景】进程-线程-协程相关问题汇总 - Go语言中文社区

【Python面试场景】进程-线程-协程相关问题汇总


经常被问及 进程, 线程, 协程之间的问题。今天在这里总结一下。

多任务的概念

简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。

并发 & 并行
  • 并发(parallel):指的是任务数多于cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
  • 并行(concurrency):指的是任务数小于等于cpu核数,即同一时刻多个任务同时在运行
进程
  • 进程是系统进行资源分配和调度的一个独立的最小的单位。
  • 程序运行在操作系统上的一个实例,就称之为进程。进程需要相应的系统资源:内存、时间片、pid。
  • 进程拥有自己独立的内存空间,进程间数据不共享,开销大。
线程
  • 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
  • 一个程序至少有一个进程,一个进程至少有一个线程。
  • 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
  • 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
  • 线程不能够独立执行,必须依存在进程中
  • 线程执行开销小,但不利于资源的管理和保护;而进程正相反。
  • 调度执行的最小单位,也叫执行路径,不能独立存在,依赖进程存在一个进程至少有一个线程,叫主线程,而多个线程共享内存(数据共享,共享全局变量),从而极大地提高了程序的运行效率。
协程(Coroutine)
  • 协程,又称微线程,纤程。
  • 协程:是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。 协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
  • 在合适的时机, gevent实现的协程可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。
  • 通俗解释:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定
协程和线程差异

在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。

操作系统为了程序运行的高效性,每个线程都由自己缓存Cache等数据,操作系统会自动实现数据的恢复操作,所以线程的切换非常耗性能。

但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。

进程-线程-协程

Python 里常常使用协程技术来代替多线程,协程是一种更轻量级的线程,进程和线程的切换时由系统决定,而协程由我们程序员自己决定,而模块 gevent 下切换是遇到了耗时操作才会切换。
三者的关系:进程里有线程,线程里有协程。

使用场景

Python 中的进程与线程的使用场景? (2018-3-30-lxy)
多进程适合在 CPU 密集型操作(cpu 操作指令比较多,如位数多的浮点运算)。
多线程适合在 IO 密集型操作(读写数据操作较多的,比如爬虫,网络编程)

GIL锁
多线程能够实现并发吗?

由于CPython的GIL(全局解释器锁)的限制,同一时刻只有一个线程被执行,而且不能利用CPU多核的特性。
线程执行时,会为当前线程上锁,其他线程等待,遇到以下两种情况会释放锁,去执行其他线程任务
​ 1. 线程遇到阻塞情况(网络请求、文件操作、队列操作)
​ 2. 调用了 time.sleep()
并不是真的并发执行,只是速度太快,看上去像并发

GIL 锁限制多线程同时执行,保证同一时间只有一个线程执行,所以 cpython 里的多线程其实是伪多线程!

死锁

若干子线程在系统资源竞争时,都在等待对方对某部分资源解除占用状态,结果是谁也不愿先解锁,互相干等着,
程序无法执行下去,这就是死锁。

线程池的优点:
  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,
    使用线程池可以进行统一的分配,调优和监控
Python库

实现并行的库有:multiprocessing
实现并发的库有:threading

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/chichu261/article/details/84799065
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2023-01-02 20:40:19
  • 阅读 ( 284 )
  • 分类:Linux

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢