Python协程

2022-09-08 13:45:36 浏览数 (1)

一、概念

子程序

在所有的语言中都是层级调用的,比如A中调用B,B在执行过程中调用C,C执行完返回,B执行完返回,最后是A执行完毕。这是通过栈实现的,一个函数就是一个执行的子程序,子程序的调用总是有一个入口、一次返回,调用的顺序是明确的

协程

又称微线程(纤程),是一种用户态的轻量级线程

理解协程

普通理解:线程是系统级别的,它们是由操作系统调度。协程是程序级别,由程序员根据需求自己调度。我们把一个线程中的一个个函数称为子程序,那么一个子程序在执行的过程中可以中断去执行别的子程序,这就是协程。也就是说同一个线程下的一段代码1执行执行着就中断,然后去执行另一段代码2,当再次回来执行代码1时,接着从之前的中断的位置继续向下执行

专业理解:协程拥有自己的寄存器上下文和栈,协程在调度切换时,将寄存器上下文和栈保存到其他的地方,在切换回来时,恢复先前保存的寄存器上下文和栈。因此,协程能后保留一次调用的状态,每次过程重入时,就相当于进入上一次调用的状态

优点

a、无需线程上下文切换的开销,协程避免了无意义的调度,从而提高了性能,但是程序员必须自己承担调度的任务,同时协程也失去了标准线程使用多CPU的能力

b、无需原子操作锁定及同步的开销

c、方便切换控制流,简化编程模型 d、高并发 高可扩展 低成本:一个CPU支持上万个协程不是问题

缺点

a、无法利用多核CPU,协程的本质是单个线程,它不能同时将多个CPU的多个核心使用上,协程需要和进程匹配使用才能运行在多个CPU上。但是一般不需要,除非是CPU计算密集型的应用

代码

代码语言:javascript复制
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run1</span><span class="hljs-params">()</span>:</span>
    print(<span class="hljs-number">1</span>)
    print(<span class="hljs-number">2</span>)
    print(<span class="hljs-number">3</span>)
    print(<span class="hljs-number">4</span>)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run2</span><span class="hljs-params">()</span>:</span>
    print(<span class="hljs-string">"a"</span>)
    print(<span class="hljs-string">"b"</span>)
    print(<span class="hljs-string">"c"</span>)
    print(<span class="hljs-string">"d"</span>)
run1()
run2()

结果

正常结果

代码语言:javascript复制
1
2
3
4
a
b
c
d

协程实现的结果(假设)

代码语言:javascript复制
<span class="hljs-number">1</span>
a
b
<span class="hljs-number">2</span>
<span class="hljs-number">3</span>
c
<span class="hljs-number">4</span>
d

二、数据传递

数据传递

代码语言:javascript复制
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func</span><span class="hljs-params">()</span>:</span>
    print(<span class="hljs-string">"------------------1"</span>)
    r = <span class="hljs-keyword">yield</span> <span class="hljs-number">1</span>
    print(<span class="hljs-string">"------------------2"</span>, r)
    <span class="hljs-keyword">yield</span> <span class="hljs-number">2</span>
    print(<span class="hljs-string">"------------------3"</span>)
    <span class="hljs-keyword">yield</span> <span class="hljs-number">3</span>
    print(<span class="hljs-string">"------------------4"</span>)
    <span class="hljs-keyword">yield</span> <span class="hljs-number">4</span>
    print(<span class="hljs-string">"------------------5"</span>)
    <span class="hljs-keyword">yield</span> <span class="hljs-number">5</span>

g = func()
<span class="hljs-comment"># print(next(g))</span>
<span class="hljs-comment"># print(next(g))</span>
<span class="hljs-comment"># print(next(g))</span>
<span class="hljs-comment"># print(next(g))</span>
<span class="hljs-comment"># print(next(g))</span>

<span class="hljs-comment"># 启动生成器g,从第二个开始send的参数值会放到yield处</span>
print(g.send(<span class="hljs-keyword">None</span>))
print(g.send(<span class="hljs-number">11</span>))

生产者与消费者

代码语言:javascript复制
<span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">product</span><span class="hljs-params">(c)</span>:</span>
    print(<span class="hljs-string">"启动生产者……"</span>)
    <span class="hljs-comment">#启动消费者</span>
    c.send(<span class="hljs-keyword">None</span>)
    <span class="hljs-keyword">for</span> data <span class="hljs-keyword">in</span> [<span class="hljs-string">"good"</span>, <span class="hljs-string">"nice"</span>, <span class="hljs-string">"cool"</span>, <span class="hljs-string">"handsome"</span>]:
        print(<span class="hljs-string">"生产出%s数据"</span>%(data))
        <span class="hljs-comment">#将数据交给消费者</span>
        c.send(data)
        time.sleep(<span class="hljs-number">2</span>)
    <span class="hljs-comment">#关闭消费者</span>
    c.close()
    print(<span class="hljs-string">"结束生产者……"</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">customer</span><span class="hljs-params">()</span>:</span>
    print(<span class="hljs-string">"启动消费者……"</span>)
    <span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>:
        print(<span class="hljs-string">"等待生产者生产数据"</span>)
        <span class="hljs-comment">#获取数据</span>
        value = <span class="hljs-keyword">yield</span>
        print(<span class="hljs-string">"消费了%s"</span>%value)

c = customer()
product(c)

0 人点赞