**前言:**所谓并发编程是指在一台处理器上"同时"处理多个任务。并发是在同一实体上的多个事件。强调多个事件在同一时间间隔发生。
1,进程、线程以及协程
【1】进程概念
我们都知道计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,统领整个计算机硬件;应用程序则是具有某种功能的程序,程序是运行于操作系统之上的。
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体
进程是一种抽象的概念,从来没有统一的标准定义。进程一般由程序、数据集合和进程控制块三部分组成。
进程状态 反映进程执行过程的变化。这些状态随着进程的执行和外界条件的变化而转换。在三态模型 中,进程状态分为三个基本状态,即运行态,就绪态,阻塞态 。在五态模型中,进程分为新建态、终止态,运行态,就绪态,阻塞态。

【2】线程概念
在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每个进程有各自独立的一块内存,使得各个进程之间内存地址相互隔离。后来,随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程序的要求了。于是就发明了线程。
线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位,
一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成。
线程的生命周期
当线程的数量小于处理器的数量时,线程的并发是真正的并发,不同的线程运行在不同的处理器上。但当线程的数量大于处理器的数量时,线程的并发会受到一些阻碍,此时并不是真正的并发,因为此时至少有一个处理器会运行多个线程。
在单个处理器运行多个线程时,并发是一种模拟出来的状态。操作系统采用时间片轮转的方式轮流执行每一个线程。现在,几乎所有的现代操作系统采用的都是时间片轮转的抢占式调度方式,如我们熟悉的Unix、Linux、Windows及macOS等流行的操作系统,
我们知道线程是程序执行的最小单位,也是任务执行的最小单位。在早期只有进程的操作系统中,进程有五种状态,创建、就绪运行、阻塞(等待)、退出。早期的进程相当于现在的只有单个线程的进程,那么现在的多线程也有五种状态,现在的多线程的生命周期与早期进程的生命周期类似。

进程与线程的区别
前面讲了进程与线程,但可能你还觉得迷糊,感觉他们很类似。的确,进程与线程有着千丝万缕的关系,下面就让我们一起来理理:
- 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
- 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
- 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源如打开文件和信号),某进程内的线程在其它进程不可见;
- 调度和切换:线程上下文切换比进程上下文切换要快得多
【3】协程(Coroutines)
协程](hlps:/so.csdn.neVso/search?g=协程&spm=1001.2101.3001.7020)fCb-routine),也可称为微线程,或非抢占式的多任务子例程,一种用户态的上下文切换技术通过一个线程实现代码块间的相互切换执行)。这种由程序员自己写程序来管理的轻量级线程叫做『用户空间线程』,具有对内核来说不可见的特性。正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程。
- 协程解决的是线程的切换开销和内存开销的问题
- *用户空间 首先是在用户空间,避免内核态和用户态的切换导致的成本,
- 由语言或者框架层调度
- *更小的栈空间允许创建大量实例(百万级别)
【4】 互斥锁
python
import time
import threading
a = 100
lock = threading.Lock()
def sub():
global a
lock.acquire()
temp = a - 1
time.sleep(0.001)
a = temp
lock.release()
l = []
for i in range(100):
t = threading.Thread(target=sub)
t.start()
l.append(t)
for j in l:
j.join()
print(a)
print(l)
【5】 线程池
系统启动一个新线程的成本是比较高的,因为它涉及与操作系统的交互。在这种情形下,使用线程池可以很好地提升性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池,
线程池在系统启动时即创建大量空闲的线程,程序只要将一个函数提交给线程池,线程池就会启动一个空闲的线程来执行它。当该函数执行结束后,该线程并不会死亡,而是再次返回到线程池中变成空闲状态,等待执行下一个函数。
此外,使用线程池可以有效地控制系统中并发线程的数量。当系统中包含有大量的并发线程时,会导致系统性能急剧下降,甚至导致解释器崩溃,而线程池的最大线程数参数可以控制系统中并发线程的数量不超过此数。
【6】 多进程实现
由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。
multiprocessing包是Python中的多进程管理包。与threading:Thread类似,它可以利用multiprocessing:Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有star0),run0),join()的方法。比外muliprocessina包中也有Lock/EventSemaphore/Condiion类(这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与treading包中的同名类一致。所以,muliprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。
【7】yield用法
python
# 迭代器和生成器:优化存储
# yield :
#1,基于yield的协程实现
import multiprocessing
import time
def foo(t):
print("foo start")
yield
print("foo end")
yield
def bar(t):
print("bar start")
yield
print("bar end")
yield
foo_ext = foo(2)
bar_ext = bar(2)
next(foo_ext)
next(bar_ext)
next(foo_ext)
next(bar_ext)
#2,基于yield的生成器对象
def cul():
for i1 in range(1,100000):
yield i1
data = cul()
for i in data:
print(i)
#3,基于yield的生成器对象函数应用
def ful():
yield 1
print("ful start")
yield 2
print("ful end")
yield 3
da = ful()
print(next(da))
print(next(da))
print(next(da))
【7】__name__用法
python
import cal
import db
cal.add()
db.MySQL()
# 模块名称: print(__name__)
#一般在启动文件中的打印都会"__main__"
#============用法
#在团队开发过程非启动模块中的测试代码可以加上下面来避免影响全局代码系统
if __name__ == '__main__':
【8】协程实现
协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。
因此: 协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
- asyncio模块
asyncio即Asynchronous 1/0是python一个用来处理并发(concurent)事件的包,是很多python异步架构的基础,多用于处理高并发网络请求方面的问题。
为了简化并更好地标识异步10,从Python 3.5开始引入了新的语法async和await,可以让coroutine的代码更简洁易读。
asyncio 被用作多个提供高性能 Pyhon 异步框架的基础,包括网络和网站服务,数据库连接库,分布式任务队列等等。
asyncio 往往是构建 IO 密集型 和高层级 结构化 网络代码的最佳选择。
【9】aiohttp
我们之前学习过爬虫最重要的模块requests,但它是阻塞式的发起请求,每次请求发起后需阻塞等待其返回响应,不能做其他的事情。本文要介绍的aiohtp可以理解成是和requests对应Python异步网络请求库,它是基于 asyncio 的异步模块,可用于实现异步爬虫,有点就是更快于 requests 的同步爬虫。安装方式,pipinstall aiohttp。
aiohtp是一个为Python提供异步HTTP 客户端/服务端编程,基于asyncio 的异步库。asyncio可以实现单线程并发I0操作,其实现了TCP、UDP、SSL等协议,aiohttp就是基于asyncio实现的http框架。
python
import aiohttp
import asyncio
async def main():
async with aiohttp.ClientSession()as session:
async with session.get("http://httpbin.org/headers") as response:
print(await response.text())
asyncio.run(main())
2,其他知识点
python
# 知识点: 将许多的分片文件有序合并成一个整体文件
ffmpeg -i index.m3u8 -c copy apple.mp4
# 知识点:
os.system #执行终端命令