GILpython
1.什麼是GIL(這是Cpython解釋器)安全
GIL本質就是一把互斥鎖,既然是互斥鎖,原理都是同樣的,都是讓多個併發線程同一時間只能有一個執行多線程
即:有了GIL的存在,同一進程內的多個線程同一時刻只能有一個在運行,意味着Cpython中一個進程下的多個線程沒法實現並行,因此就沒法利用多核優點,但不影響併發的實現併發
GIL能夠被比喻成執行權限,同一進程下的全部線程,想要執行都須要先搶執行權限dom
2.爲什麼要有GIL異步
由於Cpython解釋器自帶垃圾回收機制不是線程安全的函數
3.如何用spa
GIL vs 自定義互斥鎖線程
GIL至關於執行權限,會在任務沒法執行的狀況下,被強行釋放code
自定義互斥鎖即使是沒法執行,也不會自動釋放
4.有兩種併發解決方案:
多進程:計算密集型
多線程:IO密集型
線程queue
#1.隊列:先進先出 q=queue.Queue(3) q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get()) #2.堆棧:先進後出 q=queue.LifoQueue() q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get()) #3. 優先級隊列:優先級高先出來,數字越小,優先級越高 q=queue.PriorityQueue() q.put((3,'data1')) q.put((-10,'data2')) q.put((11,'data3')) print(q.get()) print(q.get()) print(q.get())
進程池與線程池
1.何時用池
池的功能是限制啓動的進程或線程數
何時應該限制?
當併發的任務數遠遠超過了計算機的承受能力時,即沒法一次性開啓過多的進程數或線程數時,就應該使用池的概念,將開啓的進程數或線程數限制在計算機可承受的範圍內。
2.同步vs異步
同步、異步指的是提交任務的兩種方式
同步:提交任務後就在原地等待,直到任務運行完畢後拿到任務的返回值,再繼續運行下一行代碼
異步:提交完任務(綁定一個回調函數)後根本就不在原地等待,直接運行下一行代碼,等到任務有返回值後會自動觸發回調函數
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor import os,time,random def task(n): print('%s run...' %os.getpid()) time.sleep(5) return n**2 def parse(future): time.sleep(1) res=future.result() print('%s 處理了 %s' %(os.getpid(),res)) if __name__ == '__main__': pool=ProcessPoolExecutor(4) start=time.time() for i in range(1,5): future=pool.submit(task,i) future.add_done_callback(parse) # parse會在futrue有返回值時馬上觸發,而且將future看成參數傳給parse pool.shutdown(wait=True) stop=time.time() print('主',os.getpid(),(stop - start))
線程池只須要將pool=ProcessPoolExecutor(4)改爲pool = ThreadPoolExecutor(4)便可,在使用回調時,多進程是用主進程來執行回調的,而多線程是哪一個線程閒着就由哪一個線程來執行