問題一: 計算機是如何執行程序指令的?
問題二: 計算機如何實現並發的?
輪詢調度實現並發執行 程序1-8輪詢完成,才再CPU上運行
問題三: 真正的並行需要依賴什么?
並行需要的核心條件
多進程實現並行
問題一: 什么是進程?
計算機程序是存儲在磁盤上的文件。
只有把它們加載到內存中,並被操作系統調用 它們才會擁有其自己的生命周期。
進程表示一個正在執行的程序。
每個進程都有獨立地址空間以及其他的輔助數據
進程(Process)
是計算機中已運行程序的實例
問題二: 如何在Python中使用進程?
import multiprocessing # 導入進程模塊 import datetime import time def func(data): while True: print(datetime.datetime.now()) sum = data + 100 print(sum) time.sleep(2) print(datetime.datetime.now()) if __name__ == '__main__': p = multiprocessing.Process(target=func, args=(123,)) # 創建一個進程,args傳參 必須是元組 p.start() # 運行線程p while True: time.sleep(2) print("我是主進程")
進程使用步驟
問題三: 多進程實現並行的必要條件是什么?
總進程數量不多於 CPU核心數量!
如果不滿足,那么運行的程序都是 輪詢調度產生的假象。
多線程實現並發
問題一:什么是線程?
線程被稱作輕量級進程。
線程是進程中的一個實體,操作系統不會為進程分配內存空間,它只有一點在運行中必不可少的資源
線程被包含在進程中,是進程中的實際運作單位
同一個進程內的多個線程會共享相同的上下文,
也就是共享資源(內存和數據)。
線程(thread)
是操作系統能夠進行運算調度的最小單位
問題二: 如何在Python中使用線程?
import multiprocessing # 引用進程模塊 import threading # 引用線程模塊 import time def func(data): while True: time.sleep(1) data += 1 print(data) # mult = multiprocessing.Process(target=func, args=(1314,)) # mult.start() # 運行進程 thre = threading.Thread(target=func, args=(500,)) # 創建一個線程 thre.start() # 運行線程 print("這是主進程")
進程使用步驟
問題三: 為什么多線程不是並行?
穩定性
進程具有獨立的地址空間,一個進程崩潰后,不會對其它進程產生影響。
線程共享地址空間,一個線程非法操作共享數據崩潰后,整個進程就崩潰了。 創建開銷
創建進程操作系統是要分配內存空間和一些其他資源的。開銷很大
創建線程操作系統不需要再單獨分配資源,開銷較小 切換開銷
不同進程直接是獨立的, 切換需要耗費較大資源
線程共享進程地址空間, 切換開銷小
GIL鎖(線程鎖)
Python在設計的時候,還沒有多核處理器的概念。
因此,為了設計方便與線程安全,直接設計了一個鎖。
這個鎖要求,任何進程中,一次只能有一個線程在執行。
因此,並不能為多個線程分配多個CPU。
所以Python中的線程只能實現並發,
而不能實現真正的並行。
但是Python3中的GIL鎖有一個很棒的設計,
在遇到阻塞(不是耗時)的時候,會自動切換線程。
很多庫是基於GIL鎖寫的,取消代價太大
進程可以實現並行和並發
線程只能實現並發
遇到阻塞就自動切換。
我們可以利用這種機制來
充分利用CPU
那么最后:
使用多進程與多線程來實現並發服務器
使用多進程與多線程實現並發服務器的關鍵點
關鍵點一: 多進程是並行執行,
相當於分別獨立得處理各個請求。
關鍵點二: 多線程,雖然不能並行運行,
但是可以通過避開阻塞切換線程
來實現並發的效果,並且不浪費cpu
服務端實現代碼:
import threading # 創建一個線程 import socket server = socket.socket() server.bind(('0.0.0.0', 8888)) server.listen() # 監聽 def workon(conn): while True: data = conn.recv(1024) if data == b'': conn.close() break else: print("接收到的消息: {}".format(data.decode())) conn.send(data) # 主線程 while True: conn, addr = server.accept() print("{}正在連接".format(addr)) # 線程去處理消息 p = threading.Thread(target=workon, args=(conn,)) p.start()
客戶端代碼:
import socket click = socket.socket() click.connect(('127.0.0.1', 8888)) while True: data = input("請輸入你要發送的數據:") click.send(data.encode()) print("接收到的消息: {}".format(click.recv(1024).decode()))
總結完成!
作者:含笑半步顛√
博客鏈接:https://www.cnblogs.com/lixy-88428977
聲明:本文為博主學習感悟總結,水平有限,如果不當,歡迎指正。如果您認為還不錯,歡迎轉載。轉載與引用請注明作者及出處。