1.谈谈对多进程多线程以及协成的理解
进程:一个运行的程序(代码)就是一个进程,没有运行的代码
叫做程序,进程是系统资源分配的最小单位,进程拥有自己独立的
内存空间,所以进程间数据不共享,开销大
线程:调度执行的最小单位,也叫执行路径,不能独立存在,必须
依赖进程存在,一个进程至少有一个线程,叫主线程,而多个线程共享
内存(数据共享,共享全局变量),从而极大地提高了程序的运行效率.
协成:是一种用户太的轻量级线程,协成的调度完全由用户控制,
协成拥有自己的寄存器上下文和栈.协成调度切换时,将寄存器上下文
和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文
和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局
变量,所以上下文的切换非常快
2.什么是多线程竞争?
线程是独立的,同一进程里数据共享的,当各个线程访问数据资源
时会出现竞争状态即:数据几乎被多个线程占用,造成数据混乱,即所谓
线程不安全
如何解决多线程竞争问题?锁
锁的好处?
确保了某段关键代码(共享数据资源)只能由一个线程从头到
尾完整弟执行能够解决多线程资源竞争下的原子操作问题
锁的坏处?
阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程
模式执行,效率就大大地下降了
3.什么是锁?有哪几种锁?
锁(Lock)是python提供的队线程控制的对象,
互斥锁
可重入锁
死锁
4.什么是死锁?
若干子线程在资源竞争时,都在等待对方对某部分资源解除占用状态,结果
是谁也不愿意先解锁,互相干等着,程序无法执行下去,这就是死锁
5.GIL锁,全局解释器锁(只有cpython里才有)
作用:限制多线程同时执行,保证同一时间只有一个线程执行,所有
cpython里的多线程其实是伪多线程
所以python里常常使用协成技术来代替多线程,协成是一种更轻量级的线程
进程和线程的切换时由系统决定的,而协成由我们程序员自己决定,
而模块gevent下切换时遇到了消耗操作才会切换
三者的关系:进程里有线程,线程里有协成
6.什么是线程安全?什么是互斥锁?
每个对象有对应一个可称为"互斥锁"的标记,这个标记用来保证在
任一时刻,只能有一个线程访问该对象.
同一个进程中多线程是共享系统资源的,多个线程同时对一个对象
进行操作,一个线程操作尚未结束,另一个线程已经对其进行操作,导致
最终结果出现错误,此时需要对呗操作对象添加互斥锁,保证每个线程对
该对象的操作都得到正确的结果
7.说说下面几个概念?同步,异步,非阻塞?
同步:多个任务之间有先后顺序,一个执行完下一个才能执行
异步:多个任务之间没有先后顺序,可以同时执行,有时候一个任务
可以在必要的时候后去另一个同时执行的任务的结果,这就叫回调?
阻塞:如果卡主了调用者,调用者就不能继续往下执行,就是说调用者阻塞了
非阻塞:如果不会卡主,可以继续执行,就是说非阻塞的
同步异步相对于多任务而言,阻塞非阻塞相对于代码而言
8.什么是讲师进程和孤儿进程?怎么避免僵尸进程?
孤儿进程:父进程退出,子进程还在运行的这些子进程都是孤儿进程
孤儿进程将被init进程(进程号为1)所收养,并由init进程对他们完成
状态收集工作
僵尸进程:进程使用fork创建子进程, 如果子进程退出, 而父进程
并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程
描述符仍然保存在系统中的这些进程是僵尸进程
避免僵尸进程的方法:
1. fork 两次用孙子进程去完成子进程的任务;
2. 用wait()函数使父进程阻塞
3. 使用信号量, 在signal handler 中调用waitpid, 这样父进程不用阻塞.
9.python中的进程与线程的使用场景?
多进程适合在cpu密集型操作(cpu指令比较多,如位数多的浮点运算)
多线程使用在IO密集型从操作(读写数据操作教多的,比如爬虫)
10.线程是并发还是并行?进程是并发还是并行?
线程是并发,进程是并行
进程之间相互独立,是系统分配资源的最小单位,同一进程中所有
线程共享资源
11.并行和并发?
并行:同一时刻多个任务同时运行
并发:同一时间间隔内多个任务都在运行,但是并不会再同意时刻
同时运行,存在交替执行的情况
实现并行的库有:multiprocessing
实现并发的库有:threading
程序需要执行较多的读写,请求和回复任务的需要大量的IO操作,
IO密集型操作使用并发更好
CPU运算量大的程序,使用并行会更好
12.IO密集型和CPU密集型的区别?
IO密集型:系统运作,大部分情况是CPU在对I/O(硬盘/内存)的读/写
CPU密集型:大部分时间用来做计算,逻辑判断等CPU动作的程序称为CPU密集型