python進程,線程,協程,對比,思考


【知識點回鍋】 異步服務與多線程

今天回看了去年學的分布式系統課程,講的是進程,線程,異步與回調,協程。結合最近的項目經驗,感覺對其有更深的理解了。

多進程與多線程

談到這個,不得不先說最近的項目經驗。圖像處理五千萬像素的圖片,用python單線程運行,就需要十余分鍾,多浪費時間啊!
作為一台帶多核CPU的本本,我不能忍!於是便試着去查找有關優化的方法,除了用GPU進行硬件加速處理外,第二種比較理想的方法是利用多線程或多進程。

在操作系統中,進程是資源分配的基本單位,線程是CPU調度(程序執行)的最小單位。可以這樣理解,計算機執行程序必須分配資源(一般是內存,有堆、棧、自由存儲區、全局/靜態變量區、數據區)。
這樣我給一個程序分配資源時按基本單位————進程進行分配。多進程指進程A獲得20%資源,進程B獲得30%資源…一個多進程的簡單例子是Chrome瀏覽器,可以看到Chrome占用了多個進程。
而線程是程序執行的最小單位,有時稱為輕量級進程,是CPU使用的基本單元;它由線程ID、程序計數器、寄存器集合和堆棧組成。它與屬於同一進程的其他線程共享其代碼段、數據段和其他操作系統資源(如打開文件和信號)。
線程有四種狀態:新生狀態、可運行狀態、被阻塞狀態、死亡狀態。狀態之間的轉換如下圖所示:
thread status

線程與進程的區別?

  1. 從如何創建的角度:進程是由執行程序后系統進程fork生成的,創建后生成一個PCB;線程是由父進程負責創建的,創建后生成一個TCB
  2. 從擁有資源的角度:進程擁有內存資源,有獨立的地址空間、有獨立的數據段、代碼段、堆棧段;線程擁有CPU資源,也有自己的局部變量和棧
  3. 從通信的角度:進程之間的通信只能通過進程通信(共享內存模式、消息傳遞模式、共享文件模式)進行;同一進程下線程之間的通信是通過共享的數據區進行通信的
  4. 從執行的角度:進程可以獨立執行(通過);但線程必須依附他的父進程執行

另外,不是所有語言都支持多線程多進程的編程。眾所周知,Java就是用來做web的多線程多進程的編譯型語言。
javascript是單線程引擎,不支持多線程,只能 模擬多線程;python 支持多線程!但每個線程的性能立馬給你下降30%-40%(為了保證線程安全,用全局鎖管理字典這樣復雜的數據結構再所難免)
python 難道不能開發企業級應用? 異步服務英雄上場了, Tornado 開創了這個世界, node.js 們都在學習,甚至做的更好。
有了異步,我們就可以用 單進程單線程 “並發”做爬網頁、訪問數據庫、發郵件等等工作。(注意,異步只能解決 IO 阻塞問題,而web一般就是讀寫數據存在IO阻塞,請求響應飛快)

異步服務

python異步編程主要有三種方法:回調函數、生成器法、線程大法

其中生成器是python的一個重要成果,下次分析將詳細介紹這個。
線程大法很管用,但是如果線程中訪問共享變量,就會出現 GIL 問題。

這里有介紹Tornado異步Web服務

回調函數

1
2
3
4
5
6
7
from tornado.httpclient import AsyncHTTPClient
 
def asynchronous_fetch(url, callback):
http_client = AsyncHTTPClient()
def handle_response(response):
callback(response.body)
http_client.fetch(url, callback=handle_response)

生成器法

1
2
3
4
5
6
7
8
9
10
11
from tornado import gen
 
@gen.coroutine
def fetch_coroutine(url):
http_client = AsyncHTTPClient()
response =  yield http_client.fetch(url)
# In Python versions prior to 3.3, returning a value from
# a generator is not allowed and you must use
# raise gen.Return(response.body)
# instead.
return response.body

線程大法

1
2
3
4
5
thread_pool = ThreadPoolExecutor( 4)
 
@gen.coroutine
def call_blocking():
yield thread_pool.submit(blocking_func, args)

異步總結

使用異步處理可以讓我們的應用在長時間的API和數據庫請求中免受阻塞之苦,最終更快地提供更多請求。
盡管不是所有的處理都能從異步中受益,並且實際上嘗試整個程序非阻塞會迅速使事情變得復雜,但Tornado的非阻塞功能可以非常方便的創建依賴於緩慢查詢或外部服務的Web應用。
最后盡管有了異步操作,我們還希望根據實際的應用需求定制優化方案,比如制定緩存服務器存儲經常使用的數據,比如采用負載均衡的架構使得分布式系統整體發揮最大性能。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM