python的异步

同步/异步

  • 同步:不同程序单元为完成某个任务,在执行过程中需靠某种通信方式协调一致,我们称这些程序单元是同步执行的。例如购物系统中更新商品库存,需要用“行锁”作为通信信号,让不同的更新请求强制排队顺序执行,那更新库存的操作是同步的。简言之,同步意味着有序
  • 异步:不同程序单元为完成某个任务,在执行过程中无需通信协调,也能完成任务的方式,不相关的程序单元之间可以是异步的。例如,爬虫下载网页。调度程序调用下载程序后,即可调度其他任务,而无需与该下载任务保持通信以协调行为。不同网页的下载、保存等操作都是无关的,也无需相互通知协调。这些异步操作的完成时刻并不确定。简言之,异步意味着无序

多线程

使用线程的两种方式

  • 调用函数;
t = threading.Thread(target=loop, name='')
t.start() #实例化后调用 start() 方法启动新线程,即调用了线程的 run() 方法
t.join()
  • 用类包装线程对象( 从threading.Thread 继承创建一个新的子类)

加锁

  • threading.Lock() / .acquire() / .release()
  • 给某个函数或某段代码加锁后,当某个线程开始执行此段代码时,该线程因为获得了锁,因此其他线程不能同时执行此段代码,只能等待到锁被释放后,获得该锁以后才能改。
  • 锁的好处是确保了某段关键代码只能由一个线程从头到尾完整地执行,坏处是阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率大大下降了;此外,由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁,导致多个线程全部挂起,既不能执行,也无法结束,只能靠操作系统强制终止。

协程

协程就是用户态的线程(不被操作系统内核所管理,而完全是由程序所控制, 也就是在用户态执行),其开销比线程要小。线程是操作系统内核执行上下文切换,这被称作抢占式多任务处理(Preemption);而在协程中我们自己控制上下文切换,这被称作非抢占式或合作型多任务式。(上下文切换即当多个线程正在运行时,内核可能停止当前进程,使其进入休眠状态,并选择不同的线程继续执行)

  • event loop: 当我们自己控制时,因为是我们自己处理上下文切换,所以我们需要一个调度程序,也叫做“事件循环”。此事件循环只循环遍历等待中的调度,并运行它的所有事件。每当我们产生操作时,当前任务会被添加到队列中,且第一个任务(优先级而非顺序)从队列中弹出并开始执行。事件循环,相当于一个无限循环(相当于线程池),我们可以把一些函数注册到这个事件循环上,当满足条件发生的时候,就会调用对应的处理方法。
  • task:是对协程对象的进一步封装,包含了任务的各个状态,如 running、finished 等。
#定义task的方法:
# 1.当我们将 coroutine 对象传递给 run_until_complete方法的时候,实际上它进行了一个操作就是将coroutine封装成了task对象:
loop.run_until_complete(coroutine) 

# 2.task也可以显式地进行声明:
task = loop.create_task(coroutine)

# 3.通过ensure_future方法,返回结果也是task对象,这样的话我们就可以不借助于loop来定义,即使还没有声明loop也可以提前定义好task对象:
task = asyncio.ensure_future(coroutine)
  • async:定义协程。async 定义的方法成为一个无法直接执行的 coroutine 对象,必须将其注册到事件循环中才可以执行。  (asyncio.run(coroutine)也可调用运行)
  • await:可以将耗时等待的操作挂起,让出控制权。当协程执行的时候遇到 await,时间循环就会将本协程挂起(中断),转而去执行别的协程,直到其他的协程挂起或执行完毕。(当yield from返回时,线程就可以从yield from拿到返回值,然后接着执行下一行语句。)

(syncio.coroutine把一个generator标记为coroutine类型,然后就把这个coroutine扔到EventLoop中执行。然后yield from语法可以让我们方便地在这个coroutine调用另一个generator)

Note

  • python的多线程无法利用多核,只是靠cpu的时间分配造成的并发的错觉
  • 协程是一种用户态的线程,由用户来发出中断请求以及处理响应,省去了线程的切换开销,并且所有的处理是在同一个线程下,所以也不会造成读写冲突,省去了加锁操作
  • python对协程的支持是通过generator实现的
  • asyncio是Python 3.4引入的标准库,内置了对异步IO的支持,包括async和await。asyncio的编程模型就是一个消息循环。从asyncio模块中获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO


Reference

GIL(Python不能利用多线程实现多核任务,但可以通过多进程实现多核任务[multiprocessing]。多个Python进程有各自独立的GIL锁,互不影响。)

python协程与任务

python异步爬虫
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值