GIL 锁
控制线程执行权限
当一个线程需要执行的时候、要先获得 GIL 之后才可以执行、这样就不会产生线程安全问题
在 I/O 流阻塞的时候,GIL会被释放(I/O流就是输入输出流)
什么是多进程
进程就是正在运行的程序
那什么是单进程呢?
单进程就是说你的电脑只能做一件事情
多进程
可以 “同时” 执行多个任务
什么是多线程
在一个进程里面、可以执行多个任务、每一个任务就是线程
线程可以说是程序用 CPU 的一个基本单元
单一的一个执行路径那么它就是单线程
一个程序如果有多个执行路径那么它就是多线程的
并行和并发
并行在某一个时间段里,可以同时执行多个进程
并发就是在一个时间点,同时执行多个进程
互斥锁
所谓互斥锁就是让线程乖一点别他妈的乱来一个一个线程安全有序的去执行
什么是协程(微线程)
协程也叫做微线程、在一个线程里面可以执行多个函数、线程和进程是通过系统调度的、而微线程则不需要,可以根据需要自己调度、因为微线程是函数之间在切换、所以开销很小
微线程时一般会用到 genvent、monkey.patch_all
线程池
通过线程池就可以重复利用线程、不会造成过多的浪费
处理多任务开启多进程、对于一些输入输出的多任务就开启多线程
threading 多线程模块
引入
import threading
方法
.Start() 开启线程活动
.Join () 等待,直到线程终结
.is_alive() 返回线程是否存活。
.enumerate() 返回当前所有存活的 Thread 对象的列表
.active_count() 返回当前存活的 Thread 对象的数量
.excepthook(args, /) 处理由 Thread.run() 引发的未捕获异常。
.Run() 代表线程活动的方法。
.current_thread() 返回当前对应调用者的控制线程的 Thread 对象
acquire(blocking=True, timeout=- 1) 可以阻塞或非阻塞地获得锁。
release() 释放一个锁。
为什么使用线程池
因为频繁的创建线程 销毁线程 非常的浪费资源
ThreadPoolExecutor 来实现线程池
引入
from concurrent.futures import ThreadPoolExecutor
方法
.submit(fn, /, *args, **kwargs) 调度可调用对象
.map(func, *iterables, timeout=None, chunksize=1) 类似于 map(func, *iterables) 函数,除了以下两点:
iterables 是立即执行而不是延迟执行的;
func 是异步执行的,对 func 的多个调用可以并发执行。
.shutdown(wait=True, *, cancel_futures=False)
当待执行的 future 对象完成执行后向执行者发送信号,它就会释放正在使用的任何资源
Queue 队列模块 根据队列的长度创建线程
引入
from queue import Queue
方法
.qsize() 返回队列的大致大小
大于0或小于maxsize 不保证后续 get()、put() 不被阻塞
.empty() 如果队列为空,返回 True否则False
true或false不保证后续put() 、get()不被阻塞
.full() 如果队列是满的返回 True ,否则返回 False
true或false不保证后续get() 、put()不被阻塞
.put(item, block=True, timeout=None) 将 item 放入队列。
如果可选参数 block 是 true 并且 timeout 是 None (默认),则在必要时阻塞至有空闲插槽可用。如果 timeout 是个正数,将最多阻塞 timeout 秒,如果在这段时间没有可用的空闲插槽,将引发 Full 异常。反之 (block 是 false),如果空闲插槽立即可用,则把 item 放入队列,否则引发 Full 异常 ( 在这种情况下,timeout 将被忽略)。
.put_nowait(item) 相当于 put(item, False) 。
.get(block=True, timeout=None) 从队列中移除并返回一个项目。
如果可选参数 block 是 true 并且 timeout 是 None (默认值),则在必要时阻塞至项目可得到。如果 timeout 是个正数,将最多阻塞 timeout 秒,如果在这段时间内项目不能得到,将引发 Empty 异常。反之 (block 是 false) , 如果一个项目立即可得到,则返回一个项目,否则引发 Empty 异常 (这种情况下,timeout 将被忽略)。
.get_nowait() 相当于 get(False) 。
提供了两个方法,用于支持跟踪 排队的任务 是否 被守护的消费者线程 完整的处理。
.join() 阻塞至队列中所有的元素都被接收和处理完毕。
当条目添加到队列的时候,未完成任务的计数就会增加。每当消费者线程调用 task_done() 表示这个条目已经被回收,该条目所有工作已经完成,未完成计数就会减少。当未完成计数降到零的时候, join() 阻塞被解除。
.task_done()
表示前面排队的任务已经被完成。被队列的消费者线程使用。每个 get() 被用于获取一个任务, 后续调用 task_done() 告诉队列,该任务的处理已经完成。
如果 join() 当前正在阻塞,在所有条目都被处理后,将解除阻塞(意味着每个 put() 进队列的条目的 task_done() 都被收到)。
如果被调用的次数多于放入队列中的项目数量,将引发 ValueError 异常 。



