并发编程



进程 线程

进程:
进程是一个实体。每个进程都有自己的地址空间(CPU分配)
是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程:
线程是进程中的一个实体
一个进程内部可能包含了很多顺序执行流,每个顺序执行流就是一个线程

应用场景:
多进程:cpu密集型
多线程:io密集型

协程

协程,又称微线程
协程是一种比线程更加轻量级的存在,最重要的是,协程不被操作系统内核管理,协程是完全由程序控制的。
不像线程切换需要花费操作系统的开销,线程数量越多,协程的优势就越明显。
协程不需要多线程的锁机制,因为只有一个线程,不存在变量冲突。

阻塞

阻塞调用是指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务。函数只有在得到结果之后才会返回。

常见的有网络IO阻塞, 磁盘IO阻塞,用户输入阻塞

非阻塞

程序在等待某操作过程中,自身不被阻塞,可以继续运行干别的事情,则称该程序在该操作上是非阻塞的。
非阻塞指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回

同步

同步:一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列。要么成功都成功,失败都失败,两个任务的状态可以保持一致。

异步

异步: 异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠的任务序列。

同步 阻塞

1
2
3
4
5
6
7
import requests
def test1():
print('--------开始请求url1----------')
requests.get(URL1)
print('--------开始请求url1----------') # 阻塞
requests.get(URL2)
test1()

线程异步 非阻塞

1
2
3
4
5
6
7
8
9
10
11
12
import requests
import threading
def test2():
def request(url):
t = threading.Thread(target=lambda _: requests.get(_), args=(url,))
t.start()
return t
print('开始请求url:', URL1)
request(URL1)
print('开始请求url:', URL2) # 非阻塞
request(URL2)
test2()

协程异步 非阻塞

1
2
3
4
5
6
7
8
9
10
11
import asyncio
import aiohttp
def test3():
async def request(url): #async 定义协程
print('开始请求:', url)
async with aiohttp.ClientSession() as session:
await session.get(url) # await 后是可等待对象
task = [asyncio.ensure_future(request(_)) for _ in [URL1, URL2]]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))
test3()

同步请求

1
2
3
4
5
6
7
8
def test4():
start = time.time()
url = 'https://shushugo.com/'
for _ in range(10):
result = requests.get(url)
print(result)
end = time.time()
print('用时:', end - start):

异步请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def test5():
start = time.time()

async def get(url):
async with aiohttp.ClientSession() as session:
response = await session.get(url)
return response

async def request():
url = 'https://shushugo.com/'
print('正在等待', url)
result = await get(url)
print('结果:', result)

tasks = [asyncio.ensure_future(request()) for _ in range(10)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

end = time.time()
print('用时:', end - start)