摘要:最重要的是每個線程,對應了一個函數的執行。有多個線程同時執行的時候,每個線程的狀態是由操作系統內核負責保存在內存中的。在多線程的實現中。并且內核的線程在切換多個線程的時候,線程切換的開銷是比較大。
上次的網絡編程的例子,改寫成多線程的是這樣:
import socket import thread def main(): listen_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=socket.IPPROTO_IP) listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) listen_sock.bind(("0.0.0.0", 9090)) listen_sock.listen(0) while True: conn_sock, client_addr = listen_sock.accept() thread.start_new(serve, (conn_sock, client_addr)) def serve(conn_sock, client_addr): print("connected from %s:%s" % client_addr) input = conn_sock.recv(8192) while "done" != input.strip(): conn_sock.sendall(input) input = conn_sock.recv(8192) conn_sock.sendall("bye! ") conn_sock.close() main()
變成多線程之后,就可以有多個客戶端同時連接到服務器并同時進行服務了。最重要的是每個線程,對應了一個“serve”函數的執行。所以函數執行就是有一個函數的棧,棧上有一個函數的參數和局部變量。最重要的一個局部變量就是conn_sock,有了這個socket就可以和對應的客戶端進行對話。
機器都有一個ESP的寄存器指向函數的棧頂所在的內存地址。一個cpu核只有一個ESP寄存器。有多個線程同時執行的時候,每個線程的狀態是由操作系統內核負責保存在內存中的。當這個線程被調度為執行狀態的時候,ESP寄存器被切換為當前線程的棧頂位置,然后繼續執行這個線程的后面的指令。服務器可以支持多個客戶端,就有兩個關鍵的問題要解決:
保存每個客戶端的服務狀態(最起碼要保存對應這個客戶端的socket)
一個全局scheduler來負責I/O,在需要的時候把客戶端對應的狀態切換為“當前活躍”狀態。在線程調用了阻塞的I/O操作時,操作系統內核就把線程給掛起了,同時在映射表里記錄一個對應關系,哪個I/O阻塞的fd對應的是哪個線程在等待它。等I/O阻塞條件滿足了,對應的線程就會被查表得到然后被喚醒。
在多線程的實現中。每個客戶端的狀態就是保存在線程對應函數的棧上的,而全局的scheduler就是內核的線程scheduler。這種實現方式最大的缺點是線程的棧是創建時預先分配的很大的一塊區域,大量線程會耗費過度內存。并且內核的線程scheduler在切換多個線程的時候,線程切換的開銷是比較大。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/45305.html
摘要:前面的網絡編程的例子使用多進程也是可以實現的其中之后會創建一個子進程。從效率上來說,具有多線程一樣的問題,而且內存占用會更高,切換成本也更高。多線程和多進程的版本從代碼可讀性上來說還是非常不錯的,很好懂,從上至下平鋪直敘的。 前面的網絡編程的例子使用多進程也是可以實現的: import socket import os def main(): listen_sock = s...
摘要:簡單來說就是一個操作系統提供的回調機制。其中這一步是創建,是做一個調用,后面的是輪詢,這一步是根據返回的查找對應的回調函數回調。這樣狀態從多個線程的多個棧上,變成了只有一個線程,但是在線程內部有一個來維護單線程內多個并發流程的狀態。 為了讓I/O阻塞的時候,程序還可以去干別的。除了使用線程模型,讓操作系統的內核去調度多個線程,Windows提供了IOCP機制。簡單來說就是一個操作系統提...
摘要:在了解了的實現方式的基礎之上,希望能夠把流程阻塞的功能在的框架之上實現,從而可以制作一個簡單的類似,這樣的集群調度工具。我們先來看一個最基本的網絡編程的例子這是一個服務器。 接下來,會把Python tulip這個網絡庫(也就是3.4之后的asyncio)如何實現的進行一些分析。在了解了tulip的實現方式的基礎之上,希望能夠把流程阻塞的功能在tulip的框架之上實現,從而可以制作一個...
摘要:是之后引入的標準庫的,這個包使用事件循環驅動的協程實現并發。沒有能從外部終止線程,因為線程隨時可能被中斷。上一篇并發使用處理并發我們介紹過的,在中,只是調度執行某物的結果。 asyncio asyncio 是Python3.4 之后引入的標準庫的,這個包使用事件循環驅動的協程實現并發。asyncio 包在引入標準庫之前代號 Tulip(郁金香),所以在網上搜索資料時,會經常看到這種花的...
摘要:我們可以看一下的可見是由內部支持的,其實現原理上就避免了棧進棧出的消耗,直接由最內層的返回值。另外可以實現外部直接向最內層的傳遞值,比如這段代碼的輸出是這樣傳值的方式,在用循環重新的模式下是無法實現的。這也就是必須使用,而不能使用的原因。 在python 3.3里,generator新增了一個語法 yield from 這個yield from的作用是什么?看下面兩段對比的代碼: d...
閱讀 1264·2021-10-18 13:32
閱讀 2333·2021-09-24 09:47
閱讀 1323·2021-09-23 11:22
閱讀 2463·2019-08-30 14:06
閱讀 571·2019-08-30 12:48
閱讀 1997·2019-08-30 11:03
閱讀 535·2019-08-29 17:09
閱讀 2462·2019-08-29 14:10