協程,又稱微線程或纖程,是一個比進程和線程更加輕量級的解決方案,現代編程語言基本上都支持。那麼協程究竟有什麼特色,它是如何運做的呢?
進程和線程之間的關係我在這篇文章中作了一下比較分析。線程是程序的運行流,全部指令從頭至尾按順序一一執行,進程則是包含線程的容器。在單核CPU中,永遠只有一條線程在運行,固然也只可能有一個進程運行,由操做系統內核負責進程和線程的切換。而協程是屬於用戶空間的,操做系統對其一無所知,由用戶本身去作調度。顯然用戶本身調度比經過使用一箇中斷讓操做系統調度會快不少,這就是協程快的祕訣了。php
那麼,協程到底是一種什麼樣的存在呢?上面說到線程是一條指令的執行流,那麼這個流的則由函數這些最小執行單元組成,函數則多是包涵或者調用關係,不管是那種,一個函數只有只能完畢,下一個函數才能被執行,例若有兩個函數A和B,A因爲某些緣由被阻塞,那麼B確定就不能運行。協程的出現就是爲了解決這個問題,函數能夠隨時中斷,去調用另外的函數。html
Python和PHP5.5以上版本(包含)中,能夠利用生成器中的yield在必定程度上實現協程。例如在一個車流量多的路口,攝像頭獲取車牌號,並保存到文本文件能夠這樣作:python
#!/usr/bin/env python import random def getNum(action): action.next() while True: num=random.randint(1000, 9999) #獲取車牌號,這裏隨機 stored = action.send(num) if stored > 500: break action.close() def storage(): r=0 while True: f=open("./car.txt","a") num = yield r print num if num: f.write(str(num)+"\n") r=r+1 f.close() if __name__ == "__main__": S=storage() getNum(S)
<?php function getNum($action){ while(1){ $num=rand(1000,9999); $stored = $action->send($num); if($stored > 500){ break; } } } function storage(){ $r=0; while(1){ $num=(yield $r); if($num){ echo $num."\n"; file_put_contents("./car.txt",$num."\n",FILE_APPEND); $r++; } } } $S=storage(); getNum($S);
yield這個關鍵字在不少語言中都有應用,在PHP和Python中,若是一個函數中含有yield,則這個函數會成爲一個生成器(Generator)。上面的例子中,函數之間相互調用並無在一個函數結束以後,另外一個函數纔開始運行,而是相互協做,因此稱爲」協程」,而非線程的搶佔式多任務。須要注意的是Python的yield須要用next來啓動,而PHP不須要。編程
yield只能在必定程度的實現協程,要更加深刻理解和使用協程,能夠嘗試使用gevent,gevent爲Python提供了比較完善的協程支持, 能幫助咱們自動切換協程,能夠得到極高的併發性能。併發