python多线程并发数量控制简书_Python并发时用多线程还是协程?-Go语言中文社区...

多线程想必你已经非常清楚,那么什么是协程?

协程是实现并发编程的一种方式。一说并发,你肯定想到了多线程 / 多进程模型,没错,多线程 / 多进程,正是解决并发问题的经典模型之一。最初的互联网世界,多线程 / 多进程在服务器并发中,起到举足轻重的作用。

我们知道,在处理 I/O 操作时,使用多线程与普通的单线程相比,效率得到了极大的提高。你可能会想,既然这样,为什么还需要协程(Asyncio)?

诚然,多线程有诸多优点且应用广泛,但也存在一定的局限性:

比如,多线程运行过程容易被打断,因此有可能出现竞争条件 (race condition) 的情况;再如,线程切换本身存在一定的损耗,线程数不能无限增加,因此,如果你的 I/O 操作非常耗时,多线程很有可能满足不了高效率、高质量的需求。

因此,协程是更轻量级的线程,它的切换成本非常低,相对比协程更高效一些。

那么什么场景使用多线程,什么场景使用协程呢(Asyncio)? 请参考正面的代码:

if io_bound:

if io_slow:

print('Use Asyncio')

else:

print('Use multi-threading')

else if cpu_bound:

print('Use multi-processing')

多线程和协程之间的共同点和区别:

共同点:

都是并发操作,多线程同一时间点只能有一个线程在执行,协程同一时间点只能有一个任务在执行;

不同点:

多线程,是在I/O阻塞时通过切换线程来达到并发的效果,在什么情况下做线程切换是由操作系统来决定的,开发者不用操心,但会造成竞争条件 (race condition) ;

协程,只有一个线程,在I/O阻塞时通过在线程内切换任务来达到并发的效果,在什么情况下做任务切换是开发者决定的,不会有竞争条件 (race condition) 的情况;多线程的线程切换比协程的任务切换开销更大;

对于开发者而言,多线程并发的代码比协程并发的更容易书写。

一般情况下协程并发的处理效率比多线程并发更高。

Python3 的协程使用方法

import asyncio

import aiohttp

import time

async def download_one(url):

async with aiohttp.ClientSession() as session:

async with session.get(url) as resp:

print('Read {} from {}'.format(resp.content_length, url))

async def download_all(sites):

tasks = [asyncio.create_task(download_one(site)) for site in sites]

await asyncio.gather(*tasks)

def main():

sites = [

'https://en.wikipedia.org/wiki/Portal:Arts',

'https://en.wikipedia.org/wiki/Portal:History',

'https://en.wikipedia.org/wiki/Portal:Society',

'https://en.wikipedia.org/wiki/Portal:Biography',

'https://en.wikipedia.org/wiki/Portal:Mathematics',

'https://en.wikipedia.org/wiki/Portal:Technology',

'https://en.wikipedia.org/wiki/Portal:Geography',

'https://en.wikipedia.org/wiki/Portal:Science',

'https://en.wikipedia.org/wiki/Computer_science',

'https://en.wikipedia.org/wiki/Python_(programming_language)',

'https://en.wikipedia.org/wiki/Java_(programming_language)',

'https://en.wikipedia.org/wiki/PHP',

'https://en.wikipedia.org/wiki/Node.js',

'https://en.wikipedia.org/wiki/The_C_Programming_Language',

'https://en.wikipedia.org/wiki/Go_(programming_language)'

]

start_time = time.perf_counter()

asyncio.run(download_all(sites))

end_time = time.perf_counter()

print('Download {} sites in {} seconds'.format(len(sites), end_time - start_time))

if __name__ == '__main__':

main()

## 输出

Read 63153 from https://en.wikipedia.org/wiki/Java_(programming_language)

Read 31461 from https://en.wikipedia.org/wiki/Portal:Society

Read 23965 from https://en.wikipedia.org/wiki/Portal:Biography

Read 36312 from https://en.wikipedia.org/wiki/Portal:History

Read 25203 from https://en.wikipedia.org/wiki/Portal:Arts

Read 15160 from https://en.wikipedia.org/wiki/The_C_Programming_Language

Read 28749 from https://en.wikipedia.org/wiki/Portal:Mathematics

Read 29587 from https://en.wikipedia.org/wiki/Portal:Technology

Read 79318 from https://en.wikipedia.org/wiki/PHP

Read 30298 from https://en.wikipedia.org/wiki/Portal:Geography

Read 73914 from https://en.wikipedia.org/wiki/Python_(programming_language)

Read 62218 from https://en.wikipedia.org/wiki/Go_(programming_language)

Read 22318 from https://en.wikipedia.org/wiki/Portal:Science

Read 36800 from https://en.wikipedia.org/wiki/Node.js

Read 67028 from https://en.wikipedia.org/wiki/Computer_science

Download 15 sites in 0.062144195078872144 seconds

你可能感兴趣的:(python多线程并发数量控制简书_Python并发时用多线程还是协程?-Go语言中文社区...)