协程

Golang源码探索(二) 协程的实现原理

旧街凉风 提交于 2019-12-06 15:38:37
https://www.cnblogs.com/zkweb/p/7815600.html Golang源码探索(二) 协程的实现原理 Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱, 虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻底的. 这篇文章将通过分析golang的源代码来讲解协程的实现原理. 这个系列分析的golang源代码是Google官方的实现的1.9.2版本, 不适用于其他版本和gccgo等其他实现, 运行环境是Ubuntu 16.04 LTS 64bit. 核心概念 要理解协程的实现, 首先需要了解go中的三个非常重要的概念, 它们分别是 G , M 和 P , 没有看过golang源代码的可能会对它们感到陌生, 这三项是协程最主要的组成部分, 它们在golang的源代码中无处不在. G (goroutine) G是goroutine的头文字, goroutine可以解释为受管理的轻量线程, goroutine使用 go 关键词创建. 举例来说, func main() { go other() } , 这段代码创建了两个goroutine, 一个是main, 另一个是other, 注意main本身也是一个goroutine. goroutine的新建, 休眠,

python:协程的介绍

匆匆过客 提交于 2019-12-06 11:04:51
    cpu 正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作系统强制控制):   ​一种情况是该任务发生了阻塞;   另外一种情况是该任务计算的时间过长或有一个优先级更高的程序替代了它。 1、什么是协程?    协程本质上就是一个线程,以前线程任务的切换是由操作系统控制的,遇到 I/O 自动切换,现在我们用协程的目的就是较少操作系统切换的开销(开关线程,创建寄存器、堆栈等,在他们之间进行切换等),在我们自己的程序里面来控制任务的切换。 2、通过yield实现协程   上述第二种情况并不能提升效率,只是为了让 cpu 能够雨露均沾,实现看起来所有任务都被“同时”执行的效果,如果多个任务都是纯计算的,这种切换反而会降低效率。为此我们可以基于 yield 来验证。 yield 本身就是一种在单线程下可以保存任务运行状态的方法   第一种情况的切换。在任务一遇到 io 情况下,切到任务二去执行,这样就可以利用任务一阻塞的时间完成任务二的计算,效率的提升就在于此。    yiled 可以保存状态, yield 的状态保存与操作系统的保存线程状态很像,但是 yield 是代码级别控制的,更轻量级    send 可以把一个函数的结果传给另外一个函数,以此实现单线程内程序之间的切换 import time def consumer(): while True: x=yield

爬虫高性能asyncio

心不动则不痛 提交于 2019-12-06 09:36:47
async实现协程,异步编程 我们都知道,现在的服务器开发对于IO调度的优先级控制权已经不再依靠系统,都希望采用协程的方式实现高效的并发任务,如js、lua等在异步协程方面都做的很强大。 python在3.4版本也加入了协程的概念,并在3.5确定了基本完善的语法和实现方式。同时3.6也对其进行了如解除了await和yield在同一个函数体限制等相关的优化。 asyncio是python3.4版本引入到标准库,python2x没有加这个库,毕竟python3x才是未来啊,哈哈!python3.5又加入了async/await特性。 在学习asyncio之前,要先搞清楚 同步/异步的概念 : event_loop 事件循环:程序开启一个无限的循环,程序员会把一些函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。 coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。 task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。 future: 代表将来执行或没有执行的任务的结果。它和task上没有本质的区别 async/await 关键字:python3.5 用于定义协程的关键字,async定义一个协程

Coroutine

送分小仙女□ 提交于 2019-12-06 03:42:22
Coroutine http://coolshell.cn/articles/10975.html http://www.cnblogs.com/youxin/p/3624089.html http://blog.csdn.net/wuhenyouyuyouyu/article/details/52709395 这里有个知乎的讨论,也挺好的 认为codedump说的,一语中的。 协程的好处有哪些?(知乎) 异步回调的方式,使代码进行了割裂,不那么好写,也不容易理解,使用协程就可以进行同步的写法了,生产力得到了释放 大专栏 Coroutine ,代码也变得优雅,迷人。 Making coroutines fast 这篇文章是rethinkdb在切换到协程方案,对性能的优化,里面有个性能对比的图表。哪怕针对协程调度进行优化,但是性能还是有所降低。不过是不是还是继续优化,使性能得到提高呢?毕竟线程的切换消耗是比协程切换大的。 coroutine and goroutine 这边文章讲了一些概念和通用跨平台实现方法,不涉及汇编,但我感觉如果想获得性能上的提升还是用汇编的方法,直接操作寄存器会好很多 来源: https://www.cnblogs.com/liuzhongrong/p/11961084.html

(四十四)golang--协程(goroutine)和管道(channel)相结合实例

白昼怎懂夜的黑 提交于 2019-12-06 02:51:01
统计1-8000之间的素数。 整体框架: 说明:有五个协程,三个管道。其中一个协程用于写入数字到intChan管道中,另外四个用于取出intChan管道中的数字并判断是否是素数,然后将素数写入到primeChan管道中,最后如果后面四个协程哪一个工作完了,就写入一个true到exit管道中,最后利用循环判断这四个协程是否都完成任务,并退出。 main.go package main import ( "fmt" "go_code/project_13/test" "time" ) func putNum(intChan chan int) { for i := 1; i <= 80000; i++ { intChan <- i } close(intChan) } func isPrime(n int) bool { //这里本来i只需要到int(math.Sqrt(float64(n))),为了计算时间,就直接设置i-n了 for i := 2; i <= n; i++ { if n%i == 0 { return false } } return true } func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) { for { // time.Sleep(time.Millisecond

python3通过gevent.pool限制协程并发数量

﹥>﹥吖頭↗ 提交于 2019-12-06 02:32:23
协程--gevent模块(单线程高并发) 先恶补一下知识点,上节回顾 上下文切换:当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行。这种切换称为“上下文切换”(“context switch”)       CPU会在一个上下文中执行一个线程,然后切换到另外一个上下文中执行另外一个线程,上下文切换并不廉价。如果没有必要,应该减少上下文切换的发生 进程: 一个程序需要运行所需的资源的集合每个进程数据是独立的每个进程里至少有一个线程每个进程里有可以多有个线程线程数据是共享的进程间共享数据的代价是高昂的,所以要尽量避免进程间的数据共享线程间的数据本来就是共享的线程要修改同一份数据,必须加锁,互斥锁mutex生产者消费者:1.解耦2.提高程序的运行效率,把中间等待的时间省去多线程场景: IO密集型,因为IO操作基本不占用CPU,所以多用在web,爬虫,socket交互多进程场景:CPU密集型,大数据分析,金融分析,这样用的IO就很少,因为这个进程会进行大量的运算, 但是如果切换了进程,就会变慢 协程 协程:微线程, 协程是一种用户态的轻量级线程,CPU不知道它的存在, 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候

python 高性能编程之协程

拟墨画扇 提交于 2019-12-06 01:03:16
用 greenlet 协程处理异步事件 自从 PyCon 2011 协程成为热点话题以来,我一直对此有着浓厚的兴趣。为了异步,我们曾使用多线程编程。然而线程在有着 GIL 的 Python 中带来的性能瓶颈和多线程编程的高出错风险,“协程 + 多进程”的组合渐渐被认为是未来发展的方向。技术容易更新,思维转变却需要一个过渡。我之前在异步事件处理方面已经习惯了回调 + 多线程的思维方式,转换到协程还非常的不适应。这几天我非常艰难地查阅了一些资料并思考,得出了一个可能并不可靠的总结。尽管这个总结的可靠性很值得怀疑,但是我还是决定记录下来,因为我觉得既然是学习者,就不应该怕无知。如果读者发现我的看法有偏差并指出来,我将非常感激。 多线程下异步编程的方式 线程的出现,为开发者带来了除多进程之外另一种实现并发的方式。比起多进程,多线程有另一些优势,比如可以访问进程内的变量,也就是共享资源。还有的说法说线程创建比进程创建开销低,考虑到这个问题在 Windows 一类进程创建机制很蹩脚的系统才存在,故先忽略。总的来说,线程除了可以实现进程实现的“并发执行”之外,还有另一个功能,就是管理应用程序内部的“事件”。我不知道把这种事件处理分类到异步中是不是合适,但事件处理一定是基于共享进程内资源才能实现的,所以这是多线程可以做到而多进程做不到的一点。 异步处理基于两个前提。第一个前提是支持并发

Flask源码关于local的实现

若如初见. 提交于 2019-12-05 17:45:56
flask源码关于local的实现 try: # 协程 from greenlet import getcurrent as get_ident except ImportError: try: from thread import get_ident # 导入get_ident except ImportError: from _thread import get_ident """ __storage__ = { 1111:{"stack":[汪洋] } } """ class Local(object): def __init__(self): # self.__storage__ = {} # self.__ident_func__ = get_ident object.__setattr__(self, "__storage__", {}) object.__setattr__(self, "__ident_func__", get_ident) def __iter__(self): return iter(self.__storage__.items()) def __release_local__(self): self.__storage__.pop(self.__ident_func__(), None) # 由于get_ident是一个方法

python从入门到放弃之协程

寵の児 提交于 2019-12-05 17:44:20
协程 协程,又称微线程,纤程。英文名Coroutine。 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。 所以子程序调用是通过栈实现的,一个线程就是执行一个子程序。 子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。 线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。 协程可以被认为是一种用户空间线程,与传统的抢占式线程相比,有2个主要的优点: 与线程不同,协程是自己主动让出CPU,并交付他期望的下一个协程运行,而不是在任何时候都有可能被系统调度打断。因此协程的使用更加清晰易懂,并且多数情况下不需要锁机制。 与线程相比,协程的切换由程序控制,发生在用户空间而非内核空间,因此切换的代价非常的小。 某种意义上,协程与线程的关系类似与线程与进程的关系,多个协程会在同一个线程的上下文之中运行。 协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程

线程queue

只愿长相守 提交于 2019-12-05 17:24:20
队列 import queue q = queue.Queue(3) q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get()) """ 1 2 3 """ 栈 t = queue.LifoQueue(4) t.put(1) t.put(2) t.put(3) t.put(4) print(t.get()) print(t.get()) print(t.get()) print(t.get()) """ 4 3 2 1 """ 优先级队列 p = queue.PriorityQueue(4) p.put((5,"oifjanior")) p.put((-2,"hshts")) p.put((0,"shtr")) p.put((3,"hstrhs")) print(p.get()) print(p.get()) print(p.get()) print(p.get()) """ (-2,"hshts") (0,"shtr") (3,"hstrhs") (5,"oifjanior") """ 事件event ​ 如果程序中的其他线程需要通过判断某个线程的状态来确定自己下一步的操作 版本一 from threading import current_thread, Thread import time