首先強調背景:1、gil是什麼?
gil的全稱是global interpreter lock(全域性直譯器鎖),為了資料安全所做的決定。
gil全域性直譯器鎖:同一程序下的多執行緒共享資料,共享意味著競爭,競爭帶來無序,為了資料安全所以需要加鎖進行資料保護,gil本質是一把 互斥鎖,使併發變為序列,保證同一時間只有一條執行緒訪問直譯器級別的資料,這樣就保證了直譯器級別的資料安全,同時也帶來了一些問題,同一程序只有一條執行緒執行任務,無法利用多核優勢,解決方案可以根據任務的型別來處理,如果是i/o密集型,則需要開多執行緒提高效率,如果是計算密集型則需要多程序。
2、每個cpu在同一時間只能執行乙個執行緒(在單核cpu下的多執行緒其實都只是併發,不是並行,併發和並行從巨集觀上來講
都是同時處理多路請求的概念。但併發和並行又有區別,並行是指兩個或者多個事件在同一時刻發生;而併發是指兩個或多
事件在同一時間間隔內發生。)
在python多執行緒下,每個執行緒的執行方式:
1、獲取gil
2、執行**直到sleep或者是python虛擬機器將其掛起。
3、釋放gil
可見,某個執行緒想要執行,必須先拿到gil,我們可以把gil看作是「通行證」,並且在乙個python程序中,
gil只有乙個。拿不到通行證的執行緒,就不允許進入cpu執行。什麼是協程:在python2.x裡,gil的釋放邏輯是當前執行緒遇見io操作或者ticks計數達到100(ticks可以看作是python自身的乙個計數器,專門做用於gil,每次釋放後歸零,這個計數可以通過 sys.setcheckinterval 來調整),進行釋放。
而每次釋放gil鎖,執行緒進行鎖競爭、切換執行緒,會消耗資源。並且由於gil鎖存在,python裡乙個程序永遠只能同時執行乙個執行緒(拿到gil的執行緒才能執行),這就是為什麼在多核cpu上,python的多執行緒效率並不高。
是一種使用者的輕量級的執行緒。協程擁有自己的暫存器上下文和棧。協程排程切換時,將暫存器和棧存放在制定地方,在切 換回來的時候,恢復先前的上下文和棧,
作用: 協程能保留上次呼叫的狀態,每次過程重入時,就相當於進入上次呼叫的狀態(上次離開時所處的邏輯流位置)
在併發程式設計中,協程和執行緒類似,每個協程表示乙個執行單元,擁有自己的本地資料,與其他協程共同享用全域性資料的其他資源。
為什麼使用協程:
與協程相關的是協作多工,不管是程序還是執行緒,每次阻塞、切換都要呼叫作業系統,先讓cpu 跑作業系統的執行程式,然後再讓排程程式決定先執行哪個執行緒或者程序
由於搶占式排程順序的不確定的特點,使用執行緒要非常注意處理同步問題這塊,但是協程完全不用考慮這個問題
因為協程是使用者自己編寫排程邏輯的,對cpu來說,協程就是單執行緒,cpu就不用考慮上下文排程和切換的問題,就省去了cpu排程的開銷,所有協程在一定程度上要優於執行緒
可以不受執行緒開銷的限制, 把20w左右的url放到單程序的協程都沒問題怎麼使用協程: 簡單來說,使用gevent
隱藏的問題:
總結:多程序+協程:避免了cpu排程排程的開銷,又把cpu充分的利用起來,對於爬取大量的資料資訊和檔案讀寫的效率都有很大的提高。
python 多程序 04 協程
協程是程式設計師創造出來的 單純的協程沒有作用 需要io操作時候進行切換 才有意義 原理 greenlet import greenlet def f1 print 11 gr2.switch print 33 gr2.switch def f2 print 22 gr1.switch print ...
python 多程序 協程 實現併發
使用程序池創 pool 建程序,用佇列 queue 進行程序間通訊。在子程序裡邊用協程去處理。直接上 from datetime import datetime from multiprocessing import pool,manager import asyncio from random i...
多執行緒 多程序 協程
占用的資源 程序 執行緒 協程 程序的顆粒度太大,每次都要有上下的調入,儲存,調出。執行緒 乙個軟體的執行不可能是一條邏輯執行的,必定有多個分支和多個程式段,就好比要實現程式a,實際分成 a,b,c等多個塊組合而成 這裡的a,b,c就是執行緒,也就是說執行緒是共享了程序的上下文環境,的更為細小的cp...