作為高階系列的乙個分支「併發程式設計
」,我覺得這是每個程式設計師都應該會的。
併發程式設計
這個系列,我準備了將近乙個星期,從知識點梳理,到思考要舉哪些例子才能更加讓人容易吃透這些知識點。希望呈現出來的效果真能如想象中的那樣,對小白也一樣的友好。
課程大綱
對於併發程式設計,python 的實現,總結了一下,大致有如下三種方法:
在之後的章節裡,將陸陸續續地給大家介紹到這三個知識點。
在開始講解理論知識之前,先過一下幾個基本概念。雖然咱是高階教程,但我也希望寫得更小白,更通俗易懂。
序列
:乙個人在同一時間段只能幹一件事,譬如吃完飯才能看電視;
並行
:乙個人在同一時間段可以幹多件事,譬如可以邊吃飯邊看電視;
在python中,多執行緒
和協程
雖然是嚴格上來說是序列,但卻比一般的序列程式執行效率高得很。
一般的序列程式,在程式阻塞的時候,只能幹等著,不能去做其他事。就好像,電視上播完正劇,進入廣告時間,我們卻不能去趁廣告時間是吃個飯。對於程式來說,這樣做顯然是效率極低的,是不合理的。
當然,學完這個課程後,我們就懂得,利用廣告時間去做其他事,靈活安排時間。這也是我們多執行緒
和協程
要幫我們要完成的事情,內部合理排程任務,使得程式效率最大化。
雖然多執行緒
和協程
已經相當智慧型了。但還是不夠高效,最高效的應該是一心多用,邊看電視邊吃飯邊聊天。這就是我們的多程序
才能做的事了。
為了更幫助大家更加直觀的理解,在網上找到兩張圖,來生動形象的解釋了多執行緒和多程序的區別。(侵刪)
文字總是蒼白無力的,千言萬語不如幾行**來得孔武有力。
首先,我的實驗環境配置如下
注意
以下**,若要理解,對小白有如下知識點要求:
裝飾器的運用
多執行緒的基本使用
多程序的基本使用
當然,看不懂也沒關係,主要最後的結論,能讓大家對單執行緒、多執行緒、多程序在實現效果上有個大體清晰的認識,達到這個效果,本文的使命也就完成了,等到最後,學完整個系列,不妨再回頭來理解也許會有更深刻的理解。
下面我們來看看,單執行緒,多執行緒和多程序,在執行中究竟孰強孰弱。
開始對比之前,首先定義四種型別的場景
為什麼是這幾種場景,這和多執行緒
多程序
的適用場景有關。結論裡,我再說明。
# cpu計算密集型
def count(x=1, y=1):
# 使程式完成150萬計算
c = 0
while c
c += 1
x += x
y += y
# 磁碟讀寫io密集型
def io_disk():
with open("file.txt", "w") as f:
for x in range(5000000):
f.write("python-learning\n")
# 網路io密集型
header =
# 【模擬】io密集型
def io_simulation():
time.sleep(2)
比拼的指標,我們用時間來考量。時間耗費得越少,說明效率越高。
為了方便,使得**看起來,更加簡潔,我這裡先定義是乙個簡單的時間計時器
的裝飾器。
如果你對裝飾器還不是很了解,也沒關係,你只要知道它是用於 計算函式執行時間的東西就可以了。
def timer(mode):
def deco(*args, **kw):
type = kw.setdefault('type', none)
t1=time.time()
func(*args, **kw)
t2=time.time()
cost_time = t2-t1
return deco
第一步,先來看看單執行緒的
@timer("【單執行緒】")
def single_thread(func, type=""):
for i in range(10):
func()
# 單執行緒
single_thread(count, type="cpu計算密集型")
single_thread(io_disk, type="磁碟io密集型")
single_thread(io_request,type="網路io密集型")
single_thread(io_simulation,type="模擬io密集型")
看看結果
第二步,再來看看多執行緒的
@timer("【多執行緒】")
def multi_thread(func, type=""):
thread_list =
for i in range(10):
t=thread(target=func, args=())
t.start()
e = len(thread_list)
while true:
for th in thread_list:
if not th.is_alive():
e -= 1
if e <= 0:
break
# 多執行緒
multi_thread(count, type="cpu計算密集型")
multi_thread(io_disk, type="磁碟io密集型")
multi_thread(io_request, type="網路io密集型")
multi_thread(io_simulation, type="模擬io密集型")
看看結果
第三步,最後來看看多程序
@timer("【多程序】")
def multi_process(func, type=""):
process_list =
for x in range(10):
p = process(target=func, args=())
p.start()
e = process_list.__len__()
while true:
for pr in process_list:
if not pr.is_alive():
e -= 1
if e <= 0:
break
# 多程序
multi_process(count, type="cpu計算密集型")
multi_process(io_disk, type="磁碟io密集型")
multi_process(io_request, type="網路io密集型")
multi_process(io_simulation, type="模擬io密集型")
看看結果
將結果彙總一下,製成**。
我們來分析下這個**。
首先是cpu密集型
,多執行緒以對比單執行緒,不僅沒有優勢,顯然還由於要不斷的加鎖釋放gil全域性鎖,切換執行緒而耗費大量時間,效率低下,而多程序,由於是多個cpu同時進行計算工作,相當於十個人做乙個人的作業,顯然效率是成倍增長的。
然後是io密集型,io密集型
可以是磁碟io
,網路io
,資料庫io
等,都屬於同一類,計算量很小,主要是io等待時間的浪費。通過觀察,可以發現,我們磁碟io,網路io的資料,多執行緒對比單執行緒也沒體現出很大的優勢來。這是由於我們程式的的io任務不夠繁重,所以優勢不夠明顯。
所以我還加了乙個「模擬io密集型
」,用sleep
來模擬io等待時間,就是為了體現出多執行緒的優勢,也能讓大家更加直觀的理解多執行緒的工作過程。單執行緒需要每個執行緒都要sleep(2)
,10個執行緒就是20s
,而多執行緒,在sleep(2)
的時候,會切換到其他執行緒,使得10個執行緒同時sleep(2)
,最終10個執行緒也就只有2s
.
可以得出以下幾點結論
Java併發程式設計教程
1 使用執行緒的經驗 設定名稱 響應中斷 使用threadlocal 2 executor executorservice和future 3 阻塞佇列 put和take offer和poll drainto 4 執行緒間的協調手段 lock condition wait notify notifya...
Java併發程式設計教程
多執行緒程式包含兩個或多個可同時執行的部分,每個部分可以同時處理不同的任務,從而能更好地利用可用資源,特別是當您的計算機有多個cpu時。多執行緒使您能夠寫入多個活動,可以在同一程式中同時進行操作處理。新執行緒 new 新執行緒在新的狀態下開始其生命週期。直到程式啟動執行緒為止,它保持在這種狀態。它也...
Go Context 併發程式設計教程
waitgroup 和通道 channel 是常見的 2 種併發控制的方式。如果併發啟動了多個子協程,需要等待所有的子協程完成任務,waitgroup 非常適合於這類場景,例如下面的例子 123 4567 891011 1213 1415 16var wg sync.waitgroup func d...