并发编程技术
并发任务处理,即同时执行多个任务,可以采用如下几种方案实现:
1.多进程,即创建多个进程,每个进程(其实是进程中的主线程)负责执行一个任务,由于多个进程可以同时运行,所以就可以实现并发任务处理
2,多线程:即创建多个线程,每个线程负责执行一个任务,由于多个线程可以同时运行,所以就可以实现并发任务处理
3.多进程+多线程,即创建多个进程,并且每个进程中创建多个线程
进程(Process):正在运行的程序,或程序的一次执行过程,通过PID唯一标识,它是操作系统分配资源(比如内存空间,CPU资源,I/O资源,PID资源)的基本单位,操作系统会给每个进程分配一块独立的虚拟私有地址空间,进程之间不能互访,所以进程间通信(IPC: Inter-Process Communication)比较麻烦
线程(Thread):进程内部的一条执行路径,通过TID唯一标识,线程是属于进程的,每个进程至少要有一个线程(即主线程),主线程可以创建其他多个普通线程,它是操作系统调用运行的基本单位,线程具有优先级的属性,优先级高的线程优先调用运行。一个进程内部的所有线程共享进程的所有资源,所以创建一个新线程的开销很小,速度很快。线程间相互通信也很容易实现
在单核CPU系统上,多个线程分时复用CPU(以时间片为单位),在某一时刻,其实只有一个线程在执行,其它线程都在等待,但由于CPU时间片很短,所以宏观上看来,多个线程在同时执行。而在多核CPU系统上,在某一时刻确实有多个线程在同时运行
在Python中,通过使用标准库中的threading和_ thread模块实现进程管理,_thread模块实现了底层的线程管理功能,threading模块封装了 _thread模块,即在它基础上实现的,提供的接口更好用,所以我们通常使用threading模块
两种创建线程的方式:
1.直接实例化Thread类,在构造器中传入线程函数,在线程函数中指定要执行的代码
2.子类化Thread,并重写run方法,在run方法中指定线程要执行的代码
多线程同步互斥控制
当多个线程同时对共享资源进行访问时,特别是修改操作,比如对全局变量进行修改,对同一个文件进行写操作,要进行加锁控制(使用threading.Lock类),保证互斥进行
可以使用信号量对象(threading Semaphore)控制多个线程同步进行
死锁问题
Global Interpreter Lock,全局解释器锁,在CPython解释器中,由于存在GIL机制,一个进程中的多个线程在某一时刻,只能有一个在执行Python代码,即获得GIL锁的那个线程,在它执行完100条节码后就会暂停运行并释放GIL锁,其他处于暂停状态的线程又有一个可以获得GIL锁而继续运行,所以多线程无法充分利用多核机器的计算资源,如果想提升程序在多核机器上的性能,可以使用多进程(因为每个进程都有一个独立的GIL)、编写C 扩展、使用其他Python解释器。
多进程
使用标准库multiprocessing模块实现
multiprocessing创建的子进程执行的是我们自己的程序,而subprocess创建的子进程
扩展
1.调用join方法主线程会阻塞
2.每个线程都有个线程函数,当线程执行时就会执行那个线程函数
3.真正执行任务的是线程,进程是不能执行代码的,只有线程有执行代码的能力
4.线程也称为轻量级的进程
5.高并发:同时有很多人连接到服务器,并同时处理
6.只要是有限的都是一种资源
7.内存地址的映射转换
物理地址:在操作系统中的地址
虚拟地址:在进程中虚拟的地址
8.内核越多能运行的进程越多
8核CPU可以同时运行8个进程