什么是多线程与多进程?
线程是最小的运行单元,进程是最小的资源管理单元、
串行 就是传统意义上的,同步,顺序的意思
进程:计算机中一个程序在一个数据集上 一次动态执行的过程,主要包含三部分内容
01>程序:描述进程的功能以及处理流程
02>数据集:功能处理过程中需要的资源数据
03>进程控制:严格控制进程执行过程中的各种状态
通俗来说,一个进程就是计算机上正在运行的一个程序
一个软件程序要运行,需要将软件依赖的数据加载到内存中,通过CPU进行运算并按照程序定义的逻辑结构进行流程控制,直到数据处理完成后程序退出
在程序实际执行过程中,进程只是分配需要的数据资源,是程序的主体,在程序运行时真正运的是线程,每个进程至少会有一个线程
线程
计算机中程序运行的实际执行者,每一个进程至少会有一个线程(主线程)用于执行程序
线程和进程的对比
1.一个进程可以有多个线程,但是至少有一个主线程
2.一个线程只能属于一个进程
3.一个进程中多个线程,可以共享进程中提供的数据
4.CPU运算分配给线程,CPU上执行运算的是线程
多线程编程
python2标准模块thread和threading
python3 将thread模块进行规范内置,更名为_thread(不推荐使用)推荐使用threading
import _thread
_thread.start_new_thread(function,args,kwargs = None)
function 线程要用到的方法
args 参数
主线程一旦运行结束,子线程立即停止运行
PYTHON中的多线程
threading模块的多线程并发编程机制,主要有两种操作方式
01 函数式的线程创建方式,适合面向过程程序的开发编程实现
02 面向对象的创建方式,适合面向对象程序的并发编程实现
threading的模块属性和方法(例举几个)
Thread 线程类:用于创建和管理线程
Event 事件类:用于线程同步
Condition 条件类:用于线程同步
Lock/Rlock 上锁/解锁
active_count() 获取当前alive状态的所有线程数量
current_thread() 获取当前正在执行的线程对象
get_ident() 获取运行中程序当前线程的唯一编号
Barrir 线程同步类型(wait:等待最后一个线程执行,所有线程同时执行)
ex:
获取当前存活的所有线程
threading.active_cout()
获取当前线程对象
threadind.current_thread()
threading.current_thread().getName()
threading.get_ident
获取主线程队象
threading.main_thread()
threading.main_thread.getName()
Thread类型属性和方法
init(group线程组,target目标函数,name,args可变参数,kwargs) 构造方法,创建线程类型
is_alive() 判断当前线程是否alive状态
srart() 线程启动方法
run() 线程执行方法,不可主动调用,调用start会自动调用run
join([timeout = None]) 线程独占,等待当前线程运行结束或者超时
daemon 布尔值,判断当前线程是否是守护线程
创建线程
threading.Thread()
t1.daemon = True
守护属性:如果一旦一个人被设置守护线程=True,该线程会随着主线程结束
运算和渲染不同步,有延时,人看不出来,对于计算机比较明显
《面试》问:为什么主线程执行完毕,守护线程还在执行
答:因为运算和渲染不同步,运算早就结束了,但是渲染到桌面展示上还需要一定时间,人看不出来,对于计算机比较明显
join() 独占属性
t1.join(self,timeout)
timeout 可以设置独占时间,在一定时间内只运行t1,等t1运行结束,才会运行其他线程
上锁/解锁 (lock/Rlock 互斥锁/可重用锁)
引用方法
lock = threading.Lock()
上锁
lock.acquire()
if lock.acquire():(一般加if判断语句)
解锁
lock.release()
注意解锁后是否跳出循环,不然容易死锁, 锁不会释放
Event
Queue
condition
多进程编程
多核->多硬件线程->多进程->多线程
->进程是正在执行中的应用,一个进程包含了该应用程序的所有信息,一个应用程序根据其功能的多样性,可以通过多个进程并发的形式实现
python多进程开发
->multiprocessing模块
通过该模块的process进程类型,可以很方便的创建和管理多个进程
multiprocessing常见属性和方法
Process 进程类型,用于创建和管理进程
Lock/Rlock 进程互斥锁/可重用锁,用于进程同步
Event 进程事件类型,用于进程同步
Condition 进程条件类型,用于进程同步
Queue 进程队列类型,用于多进程数据共享
Manager 专门进行数据共享的操作,本地共享,不同主机之间的网络共享
Listener\Client 监听(服务器)\客户端,基于网络多进程之间的共享
创建进程 ->multiprocessing.Process(target,args)
os.getpid() 程序的进程编号
os.getppid() 当前的进程是由哪个进程产生
Process的参数
1.name
2.daemon 是否守护进程
3.quthkey 认证码
4.exitcode 进程退出的一个错误码
5,join 占用
多进程中打印当前进程名称 multiprocessing.current_process().name
进程池(Process Pool)->存放多个进程的池塘
如果程序只是关注函数功能的运算执行->多进程只是一个多任务执行,而不是多任务的管理
进程池:可以直接 申请多个进程 提交你的任务即可
把所有任务交给进程池里面的进程处理,处理速度变快
包含多个进程的进程池,包含并且管理多个进程
init(num) 初始化函数,用于创建一个进程池
apply(fuction,args) 同步执行一个函数,当进程中的函数执行完成后才能退出
apply_async(function,args) 异步非阻塞执行一个函数
close() 停止向进程池提交任务
join() 让进程池工作完成,才能 允许其他进程继续工作
**重点
在使用进程池的时候,一定要先对进程池停止提交 不然进程池会一直接收事件不会执行,
该进程池就无法申请内存去运行,所以是一个无效的进程池,直接退出。所以要在主程序结束前停止提交,告诉主进程,进程池准备完毕,可以申请内存。pool.close(),然后开始独占运行执行进程池中的进程,pool.join(),如果不停止直接执行,程序会直接结束
进程池中的进程,默认是主进程的守护进程,主进程一旦结束,进程池里面的子进程结束
进程池的操作->把函数交给进程池处理,进程池中维护的进程会同时处理完成提交的任务->主动停止提交->独占执行->进程池里面的维护的进程就会处理任务
进程开始执行->执行函数download(得到数据之后单独执行另外一个函数)->执行下一个进程
由系统决定什么时候调用 callback 回调
创建进程池 pool = multiprocessing.Pool(5)
进程池执行函数 pool.apply_async(要执行的函数,参数,返回值)
多进程间的数据调用共享
1.全局变量可以被多个进程共享
2.多个进程使用的同一个全局变量的值是共享的
全局变量在多进程下数据是分离的
创建一个当前进程的时候就会把需要执行的方法和变量拷贝一份,运行的是拷贝的数据,不会对全局变量进行更改
可用multiprocessing的条件对象 Condition
可用multiprocessing的Queue
写多线程版本的一对一聊天(可以一直发消息,不用等服务器回复)需求分析
需要完成两个人互发信息,而且一次可以发多条信息,不需要一条一条的接收
引入模块 threading,socket