多任务
-
何谓多任务?
多任务是指在同一时间内执行多个任务。
举一个通俗易懂的例子:一台电脑中运行着多个应用程序就是多任务的一种。 -
多任务的优点
使用多任务能够充分利用CPU资源,提高程序的执行效率。 -
多任务的执行方式
并发:在一段时间内交替去执行任务。
并行:CPU多个内核真正的一起执行任务。
进程
-
进程是什么?
进程是操作系统进行资源分配的基本单位 ,每启动一个进程,操作系统就会给其分配一定的运行资源(内存)保证进程的运行。 -
关于进程的注意点
一个程序运行后至少有一个进程,一个进程默认有一个线程,一个进程可以创建多个线程,线程依附于进程存在,没有进程就没有线程。 -
如何获取进程号?
1)获取当前进程编号:os.getpid()
2)获取当前父进程编号:os.getppid() -
Python多进程的使用流程
1)导入进程包
import multiprocessing
2)创建子进程并指定执行的任务
sub_process = multiprocessing.Process(target=targe_name)
3)启动进程执行任务
sub_process.start()
-
对于Process进程类的说明
1)Process([group [, target [, name [, args [, kwargs]]]]])
group:指定进程组,目前只能使用None
target:执行的目标任务名
name:进程名字
args:以元组方式给执行任务传参
kwargs:以字典方式给执行任务传参
2)Process创建的实例对象的常用方法:
start():启动子进程实例(创建子进程)
join():等待子进程执行结束
terminate():不管任务是否完成,立即终止子进程
3)Process创建的实例对象的常用属性:
name:当前进程的别名,默认为Process-N,N为从1开始递增的整数 -
进程执行任务并传参有两种方式:
元组方式传参(args): 元组方式传参一定要和参数的顺序保持一致。
字典方式传参(kwargs): 字典方式传参字典中的key一定要和参数名保持一致。以元组方式举例,字典方式同理:
import multiprocessing import time def task(count): for i in range(count): print("任务执行中...") time.sleep(0.2) else: print("任务已完成...") if __name__ == '__main__': # args: 以元组的方式给任务传入参数 sub_process = multiprocessing.Process(target=task, args=(5,)) sub_process.start()
-
关于进程的注意点
1)进程之间不共享全局变量
创建子进程会对主进程资源进行拷贝。之所以进程之间不共享全局变量,是因为
操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相
同而已。2)主进程会等待所有的子进程执行结束再结束
为保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁。
由于这一特殊机制,我们需要设置守护主进程,使主进程退出子进程销毁不再执
行,不让主进程再等待子进程去执行。#设置守护主进程方式: sub_process.daemon = True #销毁子进程方式: sub_process.terminate()
线程
-
什么是线程?
线程是cpu调度的基本单位,每个进程至少都有一个线程(主线程)。 -
Python多线程的使用流程
1)导入线程模块import threading
2)创建子线程并指定执行的任务
sub_thread = threading.Thread(target=target_name)
3)启动线程执行任务
sub_thread.start()
-
线程类Thread参数说明
Thread([group [, target [, name [, args [, kwargs]]]]])
group: 线程组,目前只能使用None
target: 执行的目标任务名
args: 以元组的方式给执行任务传参
kwargs: 以字典方式给执行任务传参
name: 线程名,一般不用设置 -
进程执行任务并传参有两种方式:
元组方式传参(args): 元组方式传参一定要和参数的顺序保持一致。
字典方式传参(kwargs): 字典方式传参字典中的key一定要和参数名保持一致。 -
关于线程的注意点
1)线程之间执行是无序的
线程的执行顺序是由cpu调度决定的 ,cpu调度哪个线程,哪个线程就先执行,没
有调度的线程不能执行。
进程之间执行也是无序的,它是由操作系统调度决定的,操作系统调度哪个进
程,哪个进程就先执行,没有调度的进程不能执行。
2)主线程会等待所有的子线程执行结束再结束
和进程类似,我们需要设置守护主线程,使主线程退出子线程销毁不再执行。# 设置守护主线程的两种方式: # 1 sub_thread = threading.Thread(target=target_name, daemon=True) # 2 sub_thread = threading.Thread(target=target_name) sub_thread.setDaemon(True)
3)线程之间共享全局变量数据出现错误的解决方法
线程同步: 保证同一时刻只能有一个线程去操作全局变量
线程同步两种方法:1.线程等待 2.互斥锁# 线程同步方式1--线程等待(join) first_thread = threading.Thread(target=sum_num1) second_thread = threading.Thread(target=sum_num2) # 启动第一个线程 first_thread.start() # 设置线程等待 first_thread.join() # 启动第二个线程 second_thread.start()
-
互斥锁
1)概念:对共享数据进行锁定,保证同一时刻只能有一个线程去操作。
2)特点:互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到锁的线程需
要等待,等互斥锁使用完释放后,其它等待的线程再去抢这个锁。
3)使用流程# 创建互斥锁 mutex = threading.Lock() # 上锁 mutex.acquire() # 释放锁 mutex.release()
4)互斥锁总结
- 互斥锁的作用就是保证同一时刻只能有一个线程去操作共享数据,保证共享数据不会出现错误问题
- 使用互斥锁的好处确保某段关键代码只能由一个线程从头到尾完整地去执行
- 使用互斥锁会影响代码的执行效率,多任务改成了单任务执行
- 互斥锁如果没有使用好容易出现死锁的情况
-
进程与线程的对比
进程和线程都是完成多任务的一种方式。
进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位。
多进程要比多线程消耗的资源多,但是多进程开发比单进程多线程开发稳定性要强。
多进程可以使用cpu的多核运行,而多线程不行。
多线程可以共享全局变量,而多进程不行。
线程不能单独执行必须依附在进程里面。
协程
- 什么是协程?
协程是Python中另外一个实现多任务的方式。比线程占用资源更少。 - 协程的优点
1)执行效率高
2)不需要多线程的锁机制 - 协程的原理
当一个任务函数遇到IO操作时,就自动切换到其他的任务函数执行,等到IO操作完成,再在适当的时候切换回来继续执行。 - gevent的使用