一直以來寫博客都是實用主義者,只寫用法,沒信心寫原理,但是每一次寫作業的過程都有一種掘地三尺的感覺,終於,寫博客困難症重症患者經歷了漫長的思想斗爭,還是決定把從網上淘到的各種雜貨和自己的總結放在一起,寫一次原理文。。。算是繼上次裝飾器之后的第二次挖祖墳事件,只是這次是主動挖~~~
開胃菜——同步和異步
記得剛畢業那會兒,同事問我,知不知道同步和異步,我一臉茫然的搖搖頭,換來的是一臉看白痴的表情,現在漸漸明白了一些,覺得並沒有多高深。舉個栗子:你叫我去吃飯,我聽到了就立刻和你去吃飯,如果我沒聽到,你就一直叫我,直到我聽見和你一起去吃飯,這個過程叫同步;異步過程指你叫我去吃飯,然后你就去吃飯了,而不管我是否和你一起去吃飯。而我得到消息后可能立即就走,也可能過段時間再走。
所以嘍,我們不要被那些看起來晦澀的專業名詞嚇到了,不過就是吃頓飯的事兒,同事又是一臉看白痴的表情→_→:吃貨學python就只能想到吃。。。
哈哈,官方的解釋搬過來:
同步是指:發送方發出數據后,等接收方發回響應以后才發下一個數據包的通訊方式。
異步是指:發送方發出數據后,不等接收方發回響應,接着發送下個數據包的通訊方式。
初始化進程、線程與協成的概念
什么是進程?
進程,是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。前面的話我也沒懂,用非官方的白話來解釋就是——執行中的程序是進程,比如qq不是進程,但是當我們雙擊qq開始使用它的時候,它就變成了一個進程。我們寫的python程序,只有當我們執行它的時候,它才是進程。我們正在執行的IE瀏覽器,QQ,pycharm都是進程,從操作系統的角度來講,每一個進程都有它自己的內存空間,進程之間的內存是獨立的。
什么是線程?
線程,有時被稱為輕量級進程,是程序執行流的最小單元。我們可以理解為,線程是屬於進程的,我們平時寫的簡單程序,是單線程的,多線程和單線程的區別在於多線程可以同時處理多個任務,這時候我們可以理解為多線程和多進程是一樣的,我可以在我的進程中開啟一個線程放音樂,也可以開啟另外的線程聊qq,但是進程之間的內存獨立,而屬於同一個進程多個線程之間的內存是共享的,多個線程可以直接對它們所在進程的內存數據進行讀寫並在線程間進行交換。
進程與線程之間的關系
先推薦一個鏈接,這篇文章用漫畫的形式講解了進程與線程的關系:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
如上圖,假裝我們已經看完了上面的連接。這里來為偷懶的同志們解釋一下,左圖為進程與線程之間的關系。每個進程都有屬於自己的線程,至少一個。右圖是進程、單線程進程,多線程進程在內存中的情況。
關於python線程的那個傳說:
在python界一直有着一個古老的傳說,那就是python的多線程是雞肋,那么這個傳說的信度到底有多少呢?如果我們的代碼是CPU密集型(涉及到大量的計算),多個線程的代碼很有可能是線性執行的,所以這種情況下多線程是雞肋,效率可能還不如單線程,因為有context switch(其實就是線程之間的切換和線程的創建等等都是需要消耗時間的);但是:如果是IO密集型,多線程可以明顯提高效率。例如制作爬蟲,絕大多數時間爬蟲是在等待socket返回數據。這個時候C代碼里是有release GIL的,最終結果是某個線程等待IO的時候其他線程可以繼續執行。
那么,為什么我們大python會這么不智能呢?我們都知道,python是一種解釋性語言,在python執行的過程中,需要解釋器一邊解釋一邊執行,我們之前也介紹了,同一個進程的線程之間內存共享,那么就會出現內存資源的安全問題,python為了線程安全,就設置了全局解釋器鎖機制,既一個進程中同時只能有一個線程訪問cpu。作為解釋型語言,python能引入多線程的概念就已經非常不易了,目前看到的資料php和perl等多線程機制都是不健全的。解釋型語言做多線程的艱難程度可以想見。。。具體下面的鏈接推薦:python的最難問題。
正是由於python多線程的缺陷,我們在這里需要引入協成的概念。
什么是協程?
協程是一種用戶態的輕量級線程。如果說多進程對於多CPU,多線程對應多核CPU,那么事件驅動和協程則是在充分挖掘不斷提高性能的單核CPU的潛力。我們既可以利用異步優勢,又可以避免反復系統調用,還有進程切換造成的開銷,這就是協程。協程也是單線程,但是它能讓原來要使用異步+回調方式寫的非人類代碼,可以用看似同步的方式寫出來。它是實現推拉互動的所謂非搶占式協作的關鍵。對於python來說,由於python多線程中全局解釋器導致的同時只能有一個線程訪問cpu,所以對協程需求就相比於其他語言更為緊迫。
進程、線程與協程
從硬件發展來看,從最初的單核單CPU,到單核多CPU,多核多CPU,似乎已經到了極限了,但是單核CPU性能卻還在不斷提升。server端也在不斷的發展變化。如果將程序分為IO密集型應用和CPU密集型應用,二者的server的發展如下:
IO密集型應用: 多進程->多線程->事件驅動->協程
CPU密集型應用:多進程-->多線程
調度和切換的時間:進程 > 線程 > 協程
偷懶的同學看這里→_→:不需要實現復雜的內存共享且需利用多cpu,用多進程;實現復雜的內存共享及IO密集型應用:多線程或協程;實現復雜的內存共享及CPU密集型應用:協程
開始寫連載的博客了,哈哈,感覺還是短短的文章可讀性強~~~
進程、線程和協成的詳解如下:
進程篇:http://www.cnblogs.com/Eva-J/articles/5110844.html
線程篇——基礎篇:http://www.cnblogs.com/Eva-J/articles/5109737.html
線程篇——進階篇:http://www.cnblogs.com/Eva-J/articles/5110160.html
線程篇——線程池:http://www.cnblogs.com/Eva-J/articles/5106564.html
協程篇:http://www.cnblogs.com/Eva-J/articles/5110969.html
參考文獻:
同步和異步相關:http://jingyan.baidu.com/article/295430f1cbfa8f0c7e0050ab.html
python的最難問題【譯】多線程相關:http://www.oschina.net/translate/pythons-hardest-problem
淺談對協程的理解:http://blog.csdn.net/qq910894904/article/details/41699541