併發編程中使用到的模塊:html
多進程:python
multiprocessing包 linux
開啓進程:multiprocessing.Process, (from multiprocessing import Process)nginx
進程池:multiprocessing.Pool, (requests,from urllib.request import urlopen 爬蟲有用到)數據庫
進程間同步控制:multiprocessing.Lock multiprocessing.Semaphore multiprocessing.Eventdjango
進程間通訊:multiprocessing.Queue multiprocessing.Pipe編程
進程間數據共享:multiprocessing.Manager 服務器
多線程:網絡
threading包:多線程
threading.Thread
threading.Lock
threading.RLock
threading.Semaphore,Event
queue(線程中的隊列),注意是普通隊列
線程池(concurrent.futures)
from concurrent.futures import ThreadPoolExecutor t = ThreadPoolExecutor(max_workers=5)
t.submit(func,i) ##異步開啓線程,相似 apply_async #線程池也不用 target= 了, 可是傳參是直接傳 不用args=
協程:
greenlet模塊,gevent模塊
IO模型:
select模塊,selector模塊
異步框架:twisted,tornado
同步框架:django
須要開啓多進程/線程,而且須要 start()方法的:
Process(target=,args=()) :RLock,Lock,Semaphore,Event,Queue,Pipe,都要實例化後,把這個實例化傳入 args,而後再使用
Thread(target=,args=()) :RLock,Lock,Semaphore,Event,Condition,都要實例化後,把這個實例化傳入 args,而後再使用
直接開啓進程/線程,不用target,不用start方法:
進程池:開啓異步多進程 p = Pool(5), p.apply_async
Pool.apply_async(func,args,args=(x,y,...),callback=func2) #進程池中不用target=了,直接寫函數名,可是傳參仍是要用args=,回調函數 callback=函數2名字
線程池:from concurrent.futures import ThreadPoolExecutor t = ThreadPoolExecutor(max_workers=5)
t.submit(func,i) ##異步開啓線程,相似 apply_async #線程池也不用 target= 了, 可是傳參是直接傳 不用args=
多線程的定時器,不須要 Thread實例化:
Timer(2,func).start() #注意,此處Timer是異步不阻塞的,這裏的2秒是針對函數來講的,它起了線程後,會立刻執行後面的代碼
#進程的缺點: # 進程只能在一個時間幹一件事,若是想同時幹兩件事或多件事,進程就無能爲力了。 # 進程在執行的過程當中若是阻塞,例如等待輸入,整個進程就會掛起,即便進程中有些工做不依賴於輸入的數據,也將沒法執行。 # 60年代,在OS中能擁有資源和獨立運行的基本單位是進程,然而隨着計算機技術的發展,進程出現了不少弊端, # 一是因爲進程是資源擁有者,建立、撤消與切換存在較大的時空開銷,所以須要引入輕型進程;二是因爲對稱多處理機(SMP)出現, # 能夠知足多個運行單位,而多個進程並行開銷過大。 # 所以在80年代,出現了···能獨立運行的基本單位——線程(Threads)。 # ······注意:進程是資源分配的最小單位,線程是CPU調度的最小單位. #因此說進程間都有各自的內存空間,只能通訊來獲取數值 # 每個進程中至少有一個線程 #能夠把進程看作一個車間,每一個進程確定有一個主線程,類比車間一定有一個工人(主線程) #把線程看做車間的工人 #CPU就是生產零件的機器,工人搬材料給cpu製做。此時若是要多生產零件,咱們平時都是在一直增長車間(即增長進程),從而多了工人來運做零件製造 #可是增長線程,就比如只在一個車間裏增長工人,就每必要每次都要新開車間,時空開銷這麼大了 #在操做系統中的 分時調度系統裏,咱們所說的切換進程,其實就是切換進程的主線程 #內存中的進程: #從頭至尾 棧,堆,數據,文本 #進程中有: #代碼,數據,文件 線程(線程有 寄存器,棧,線程自己) # 線程有 寄存器,棧,線程自己 # 線程與進程的區別能夠概括爲如下4點: # 1)地址空間和其它資源(如打開文件):進程間相互獨立,同一進程的各線程間共享。某進程內的線程在其它進程不可見。 # 2)通訊:進程間通訊IPC,線程間能夠直接讀寫進程數據段(如全局變量)來進行通訊——須要進程同步和互斥手段的輔助,以保證數據的一致性。 # 3)調度和切換:線程上下文切換比進程上下文切換要快得多。 #有時也稱作進程切換或任務切換,是指CPU 從一個進程或線程切換到另外一個進程或線程。 # 4)在多線程操做系統中,進程不是一個可執行的實體。 #真正執行的是線程 #http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html #線程特色 #1.輕型實體,佔用很是小的資源 #2.獨立調度和分派的基本單位:即cup實際上調度的是線程 #3.共享進程資源 #4.可併發執行 #協程: #本質上是一個線程 #可以在多個任務之間切換來節省一些IO時間 #協程中任務之間的切換也消耗時間,可是開銷遠遠小於進程線程之間的切換 #協程的意義: #在遇到IO操做的時候,切換到另一個任務 #規避以前任務的IO時間,來提升cpu的利用率 #在實際工做中會採用:進程+線程+協程,來提升代碼的併發效果 #進程是cpu核數+1,線程是cpu核數*5,每一個線程中協程最多能夠起500個 #好比: #發送了一個網頁請求後,在網絡延時,等待網頁響應的時間(等待IO),就能夠用協程去切換任務利用等待的時間,繼續發送多個網頁請求,從而提升效率 #進程5,線程20,協程500 = 總共能夠有50000個協程:一臺4c的機器最多能夠接收的併發數 #數據庫,負載均衡,讓不少個請求,平均分攤給各個服務器 #nginx組件 大型互聯網公司會用到,就是用來幫你分發任務的,併發最大承載量就是50000,用的就是協程機制 #通常狀況下就是根據這個規則,上下浮動
# 主進程 # 子進程 # 開啓了子進程的主進程 : # 主進程本身的代碼若是長,等待本身的代碼執行結束, # 子進程的執行時間長,主進程會在主進程代碼執行完畢以後等待子進程執行完畢以後 主進程才結束 #···子進程不必定要依賴運行着的父進程 #至於父進程若是關閉了 可是子進程沒運行完, #好比 控制檯 python XXX.py 運行了py文件,此時若是關閉了控制檯,py文件是否會跟着關閉? #在linux中 若是 python XXX.py & 後面跟上&則 py文件會一直在後臺運行 #因此,關閉父進程,子進程是否關閉要看是怎麼規定的
#和進程同樣,主線程會等到子線程執行完才結束。 設置守護線程也是 t.daemon=Ture #守護進程會隨着主進程的結束而結束 #守護線程會在主線程結束以後等待子線程的結束才結束,主進程只是代碼運行結束,可是沒關閉,由於主進程要留着內存資源給子線程用 #可是若是進程既有子線程,也有子進程,會等到全部代碼結束完,才結束。由於主進程沒結束,因此守護線程還會運行