目录

 

1.概述

2.多线程(threading模块)

3.队列(queue模块)

4.多进程(multiprocessing模块)


之前学习的程序都是单步骤的,即执行完上一句才开始执行下一句,也称为单任务,单任务程序虽然简单易懂但性能低。多任务是解决这一问题引出的,它能同时让计算机执行多个任务,有着异步与高效的特点。Python中提供了threading、multiprocessing模块来实现多任务,接下来让我们学习一下吧。

 

1.概述

并发与非并发:

非并发编程:程序由单个步骤序列构成;包含独立子任务的程序执行性能低

并发编程:异步,高效;分解子任务、简化流程与逻辑

进程概念process:

是程序的执行实例

每个进程都有自己的地址空间、内存、数据栈与辅助数据

线程概念thread:

在同一进程内,可被并行激活的控制流

共享相同的上下文(即地址空间、数据结构)

便于信息共享和通信

线程的访问顺序差异会导致程序结果不一致

Python GIL全局解释器锁

Python代码由虚拟机(解释器主循环)控制,主循环同时只能有一个控制线程执行

这样导致Python的多线程只在IO密集型程序上有所作用,在计算密集型上只能用进程(但会消耗更多的资源)或者用底层语言编写

 

 

2.多线程(threading模块)

顺序执行一个4秒代码和2秒代码会消耗6秒时间,如下图

python并发写入pg python 并发编程_python并发写入pg

threading模块实现多线程

构造方法1:

.Thread(target = 目标函数,args=(参数,))

其他方法:

.start() 启动线程

.join() 要求主线程等待

.current_thread().name 获取当前线程名称

python并发写入pg python 并发编程_多线程_02

python并发写入pg python 并发编程_进程池_03

上述代码我们发现主线程不会等待子线程运行结束,我们希望主线程等待子线程需要使用.join()方法

python并发写入pg python 并发编程_Python_04

python并发写入pg python 并发编程_python并发写入pg_05

构造方法2:

自定义Thread派生类,重新run方法逻辑(注意run方法内部将参数元组解包,详见Python基础知识学习(五)——函数)

python并发写入pg python 并发编程_进程池_06

python并发写入pg python 并发编程_多线程_07

当使用多线程时经常会发生多人同时使用资源而发生错乱的问题,如下图我们想让每个人按顺序放入123鸡蛋,错乱代码如下

 

python并发写入pg python 并发编程_python并发写入pg_08

python并发写入pg python 并发编程_多线程_09

python并发写入pg python 并发编程_python并发写入pg_10

想要解决这一问题最简单的方式是使用同步锁

创建锁:

threading.Lock()

锁方法:

.acquire()   获得锁

.release()   释放锁

锁也支持上下文操作:

with 锁:

python并发写入pg python 并发编程_python并发写入pg_11

python并发写入pg python 并发编程_python并发写入pg_12

使用上下文with的锁

python并发写入pg python 并发编程_进程池_13

 

 

3.队列(queue模块)

队列保证多线程环境下共享操作的顺序

队列分类:

先进先出队列 Queue

先进后出(栈)LifoQueue

优先队列  PriorityQueue

构造队列

queue.Queue(maxsize=0)

方法

.put(item, block=True, timeout=None)   放入数据项,timeout指定几秒超时

.get(block = True, timeout =None)  获取数据项

.Empty()   查看队列是否为空

.task_done()   声明当前队列任务处理完毕

.join()  队列所有项处理完毕前阻塞

python并发写入pg python 并发编程_Python_14

python并发写入pg python 并发编程_多线程_15

执行结果:

python并发写入pg python 并发编程_Python_16

 

 

4.多进程(multiprocessing模块)

由于Python的全局解释器锁使得多线程优化的结果非常有限,多线程仅仅适用于IO密集型的操作,对计算密集型没有太大效果。而多进程充分利用多核、多cpu的计算能力,适用于计算密集型任务。即IO密集型多考虑多线程,计算密集型多考虑多进程。

构造进程:

multiprocessing.Process(target=目标函数, args=(参数,))

方法:

.start() 启动线程

.join() 要求主进程等待 

.current_process()   获取当前进程  进程名称 .name

python并发写入pg python 并发编程_python并发写入pg_17

python并发写入pg python 并发编程_Python_18

进程池:

concurrent.futures 模块(弃用)——ThreadPoolExecutor 线程池、ProcessPoolExecutor 进程池

multiprocessing模块:现在进程池已经被添加到进程模块中

创建进程池   multiprocessing.Pool()

创建线程池   multiprocessing.ThreadPool()

阻塞方式运行   .apply(func, args)

非阻塞方式运行   apply_async(func, args)

关闭进程池   .close()

回收进程池   .join()

python并发写入pg python 并发编程_Python_19

python并发写入pg python 并发编程_多线程_20

python并发写入pg python 并发编程_Python_21

python并发写入pg python 并发编程_进程池_22

python并发写入pg python 并发编程_进程池_23