1. 程式人生 > >python 學習第二十三天(Cpython直譯器中的GIL)

python 學習第二十三天(Cpython直譯器中的GIL)

    首先讓我們瞭解一下併發和並行的概念:什麼是併發什麼是並行,他們的區別是什麼?
    舉個簡單的例子:
    你吃飯吃到一半,電話來了,你一直到吃完了以後才去接,這就說明你不支援併發也不支援並行.
    
    你吃飯吃到一半,電話來了,你停了下來接了電話,接完後電話以後繼續吃飯,這說明你支援併發。
    
    你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支援並行。

    並行與併發的理解
    併發:交替處理多個任務的能力;
    並行:同時處理多個任務的能力;
    併發的關鍵是你有處理多個任務的能力,不一定要同時。
    
    並行的關鍵是你有同時處理多個任務的能力,強調的是同時.
    
    所以它們最大的區別就是:是否是『同時』處理任務。
    
    對於一個多核cpu來說並行顯然要比並發快的多
    由此我們可以知道一個多核cpu在處理多個任務的時候如果想要發揮最大功效就要實現並行
    
    那我們在使用多執行緒和多程序來寫程式的時候就是為了讓多核cup發揮他最大的功效實現並行,
也就是我們面試題參考答案的結果
    
    程式碼驗證多程序,多執行緒對cpu的使用情況
    
    1.多執行緒實驗

    子執行緒死迴圈
    import threading
    
    def test():
     while True:
     pass
    
    t1 = threading.Thread(target=test)
    t1.start()

    2.主執行緒死迴圈
    while True:
     pass

    3.多程序
    import multiprocessing
    
    def deadLoop():
     while True:
     pass
    子程序死迴圈
    p1 = multiprocessing.Process(target=deadLoop)
    p1.start()
    主程序死迴圈
    deadLoop()

    通過程式碼可以發現 多程序可以充分使用cpu的兩個核心 而多執行緒卻不能充分使用cpu的兩個核心
    問題 : 通過驗證我們發現多執行緒並不能真正的讓多核cpu實現並行。
    原因 :
    cpython直譯器中存在一個GIL(全域性直譯器鎖),他的作用就是保證同一時刻只有一個執行緒可以執行程式碼,
因此造成了我們使用多執行緒的時候無法實現並行。

    解決方案法 :
    1:更換直譯器 比如使用jpython(java實現的python直譯器)
    2:使用多程序完成多工的處理,但多程序開銷比較大

    GIL(全域性直譯器鎖)
    常見GIL面試題如下
    描述Python GIL的概念, 以及它對python多執行緒的影響?編寫一個多執行緒抓取網頁的程式,
並闡明多執行緒抓取程式是否可比單執行緒效能有提升,並解釋原因。

    Guido的宣告:點選開啟連結   
he language doesn’t require the GIL – it’s only the CPython virtual machine that has historically
been unable to shed it.
    參考答案:
    Python語言和GIL沒有半毛錢關係。僅僅是由於歷史原因在Cpython虛擬機器(直譯器),難以移除GIL。
    GIL:全域性直譯器鎖。每個執行緒在執行的過程都需要先獲取GIL,保證同一時刻只有一個執行緒可以執行程式碼。
    執行緒釋放GIL鎖的情況: 在IO操作等可能會引起阻塞的system call之前,可以暫時釋放GIL,但在執行完畢後,
必須重新獲取GIL Python 3.x使用計時器(執行時間達到閾值後,當前執行緒釋放GIL)或Python 2.x,tickets計數
達到100
    Python使用多程序是可以利用多核的CPU資源的。
    多執行緒爬取比單執行緒效能有提升,因為遇到IO阻塞會自動釋放GIL鎖
    結論:
    1. 在 處理像科學計算 這類需要持續使用cpu的任務的時候 單執行緒會比多執行緒快
    2. 在 處理像IO操作等可能引起阻塞的這類任務的時候 多執行緒會比單執行緒
    首先讓我們瞭解一下併發和並行的概念:什麼是併發什麼是並行,他們的區別是什麼?
    舉個簡單的例子:
    你吃飯吃到一半,電話來了,你一直到吃完了以後才去接,這就說明你不支援併發也不支援並行.
    
    你吃飯吃到一半,電話來了,你停了下來接了電話,接完後電話以後繼續吃飯,這說明你支援併發。
    
    你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支援並行。
    並行與併發的理解
    併發:交替處理多個任務的能力;
    並行:同時處理多個任務的能力;
    併發的關鍵是你有處理多個任務的能力,不一定要同時。
    
    並行的關鍵是你有同時處理多個任務的能力,強調的是同時.
    
    所以它們最大的區別就是:是否是『同時』處理任務。
    
    對於一個多核cpu來說並行顯然要比並發快的多
    由此我們可以知道一個多核cpu在處理多個任務的時候如果想要發揮最大功效就要實現並行
    
    那我們在使用多執行緒和多程序來寫程式的時候就是為了讓多核cup發揮他最大的功效實現並行,
也就是我們面試題參考答案的結果
    
    程式碼驗證多程序,多執行緒對cpu的使用情況
    
    1.多執行緒實驗

    子執行緒死迴圈
    import threading
    
    def test():
     while True:
     pass
    
    t1 = threading.Thread(target=test)
    t1.start()

    2.主執行緒死迴圈
    while True:
     pass

    3.多程序
    import multiprocessing
    
    def deadLoop():
     while True:
     pass
    子程序死迴圈
    p1 = multiprocessing.Process(target=deadLoop)
    p1.start()
    主程序死迴圈
    deadLoop()

    通過程式碼可以發現 多程序可以充分使用cpu的兩個核心 而多執行緒卻不能充分使用cpu的兩個核心
    問題 : 通過驗證我們發現多執行緒並不能真正的讓多核cpu實現並行。
    原因 :
    cpython直譯器中存在一個GIL(全域性直譯器鎖),他的作用就是保證同一時刻只有一個執行緒可以執行程式碼,
因此造成了我們使用多執行緒的時候無法實現並行。

    解決方案法 :
    1:更換直譯器 比如使用jpython(java實現的python直譯器)
    2:使用多程序完成多工的處理,但多程序開銷比較大

    GIL(全域性直譯器鎖)
    常見GIL面試題如下
    描述Python GIL的概念, 以及它對python多執行緒的影響?編寫一個多執行緒抓取網頁的程式,
並闡明多執行緒抓取程式是否可比單執行緒效能有提升,並解釋原因。

    Guido的宣告:點選開啟連結   
he language doesn’t require the GIL – it’s only the CPython virtual machine that has historically
been unable to shed it.
    參考答案:
    Python語言和GIL沒有半毛錢關係。僅僅是由於歷史原因在Cpython虛擬機器(直譯器),難以移除GIL。
    GIL:全域性直譯器鎖。每個執行緒在執行的過程都需要先獲取GIL,保證同一時刻只有一個執行緒可以執行程式碼。
    執行緒釋放GIL鎖的情況: 在IO操作等可能會引起阻塞的system call之前,可以暫時釋放GIL,但在執行完畢後,
必須重新獲取GIL Python 3.x使用計時器(執行時間達到閾值後,當前執行緒釋放GIL)或Python 2.x,tickets計數
達到100
    Python使用多程序是可以利用多核的CPU資源的。
    多執行緒爬取比單執行緒效能有提升,因為遇到IO阻塞會自動釋放GIL鎖
    結論:
    1. 在 處理像科學計算 這類需要持續使用cpu的任務的時候 單執行緒會比多執行緒快
    2. 在 處理像IO操作等可能引起阻塞的這類任務的時候 多執行緒會比單執行緒