高效能python程式設計之協程(stackless)

高洛峰
發布: 2016-10-18 10:05:10
原創
1452 人瀏覽過

我們都知道並發(不是並行)程式目前有四種方式,多進程,多線程,非同步,和協程。

多進程編程在python中有類似C的os.fork,當然還有更高層封裝的multiprocessing標準庫,在之前寫過的python高可用程序設計方法http://www.cnblogs.com/hymenz/ p/3488837.html中提供了類似nginx中master process和worker process間訊號處理的方式,保證了業務進程的退出可以被主進程感知。

多線程程式設計python中有Thread和threading,在linux下所謂的線程,實際上是LWP輕量級進程,其在核心中具有和進程相同的調度方式,有關LWP,COW(寫時拷貝), fork,vfork,clone等的資料較多,這裡不再贅述。

非同步在linux下主要有三種實作select,poll,epoll,關於非同步不是本文的重點。

說協程肯定要說yield,我們先來看一個例子:

#coding=utf-8
import time
import sys
# 生产者
def produce(l):
    i=0
    while 1:
        if i < 5:
            l.append(i)
            yield i
            i=i+1
            time.sleep(1)
        else:
            return
      
# 消费者
def consume(l):
    p = produce(l)
    while 1:
        try:
            p.next()
            while len(l) > 0:
                print l.pop()
        except StopIteration:
            sys.exit(0)
l = []
consume(l)
登入後複製

在上面的例子中,當程式執行到produce的yield i時,返回了一個generator,當我們在custom中調用p.next (),程式又回到produce的yield i繼續執行,這樣l中又append了元素,然後我們print l.pop(),直到p.next()引發了StopIteration異常。

透過上面的例子我們看到協程的調度對於核心來說是不可見的,協程間是協同調度的,這使得並發量在上萬的時候,協程的性能是遠高於線程的。

import stackless
import urllib2
def output():
    while 1:
        url=chan.receive()
        print url
        f=urllib2.urlopen(url)
        #print f.read()
        print stackless.getcurrent()
     
def input():
    f=open(&#39;url.txt&#39;)
    l=f.readlines()
    for i in l:
        chan.send(i)
chan=stackless.channel()
[stackless.tasklet(output)() for i in xrange(10)]
stackless.tasklet(input)()
stackless.run()
登入後複製

關於協程,可以參考greenlet,stackless,gevent,eventlet等的實作。

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!