1. 程式人生 > >並發編程/GIL

並發編程/GIL

提高 同方 系統 是否 弊端 編寫 color 有時 計算機系統

進程:

進程就是一個程序在一個數據集上的一次動態執行過程。進程一般由程序、數據集、進程控制塊三部分組成。我們編寫的程序用來描述進程要完成哪些功能以及如何完成;數據集則是程序在執行過程中用它來控制和管理進程,它是系統感知進程存在的唯一標識。

為了實現多道技術,使CPU使用率更高,系統會經常進行進行間的切換,切換會發生在出現IO操作的時候,以及系統固定時間的切換。

線程:

線程的出現是為了降低上下文切換的消耗,提高系統的並發性,並突破一個進程只能幹一樣事的缺陷,使到進程內並發成為可能。線程也叫輕量級進程,它是一個基本的CPU執行單元,也是程序執行過程中的最小單元,由線程ID、程序計數器、寄存器集合和堆棧共同組成。線程的引入減小了程序並發執行時的開銷,提高了操作系統的並發性能。線程沒有自己的系統資源。

進程與線程的關系:

1.一個線程只能屬於一個進程,而一個進程可以有多個線程,但至少有一個線程。

2.資源分配給進程,同一進程的所有線程共享進程的所有資源。

3.CPU分給線程,即真正在CPU上進行的是線程。
Pyhon的多線程:由於GIL導致同一時刻同一進程只能有一個線程。

並行和並發:

並行處理(Parallel Processing)是計算機系統中能同時執行兩個或更多個處理的一種計算方法。並行處理可同時工作於同一程序的不同方面。並行處理的主要目的是節省大型和復雜問題的解決時間。並發處理(concurrency Processing):指一個時間段中有幾個程序都處於已啟動運行到運行完畢之間,且這幾個程序都是在同一個處理機(CPU)上運行,但任一個時刻點上只有一個程序在處理機(CPU)上運行

並發的關鍵是你有處理多個任務的能力,不一定要同時。並行的關鍵是你有同時處理多個任務的能力。所以說,並行是並發的子集

threading模塊

線程對象的創建:

thread直接創建:

 1  1 import time
 2  2 import threading
 3  3 def tingge():
 4  4      print(聽歌)
 5  5      time.sleep(3)
 6  6      print(聽歌結束)
 7  7 
 8  8 def xieboke():
 9  9      print(寫博客)
10 10      time.sleep(5)
11 11 print(寫博客結束) 12 12 13 13 t1 = threading.Thread(target = tingge) #生成線程實例,target=函數名,args = 函數需要傳參的參數,默認可以不傳 14 14 t2 = threading.Thread(target = xieboke) 15 15 16 16 t1.start()   #啟動進程 17 17 t2.start() 18 18 print("ending!") 19 20 21 #繼承Thread式自定義創建: 22 import threading 23 import time 24 class MyThread(threading.Thread): 25 26 def __init__(self,num): 27 threading.Threa.__init__(self) 28 self.num = num 29 def run(self): 30 print("running on number:%s" % self.num ) 31 time.sleep(3) 32 33 t1 = MyThread(56) 34 t2 = MyThread(78) 35 36 t1.start() 37 t2.start() 38 print(ending)

以上第一段代碼就實現了一個並發的效果。tingge與xieboke函數(子線程)跟主邏輯“print(‘ending!‘)”(主線程)同時啟動,先幾乎同時執行【print(‘聽歌‘)、print(‘寫博客‘)、print("ending!")】隨後IO操作“sleep”,等3S聽歌結束,再等2S寫博客結束。如果使用串行的方法,程序全部執行則一共需要差不多8S的時間,降低了CPU的使用效率。

Threading的方法:

join:在子線程完成運行之前,這個子線程的父線程將一直被阻塞。

setDaemon:

 ‘‘‘
         將線程聲明為守護線程,必須在start() 方法調用之前設置,如果不設置為守護線程程序會被無限掛起。

         當我們在程序運行中,執行一個主線程,如果主線程又創建一個子線程,主線程和子線程 就分兵兩路,分別運行,那麽當主線程完成

         想退出時,會檢驗子線程是否完成。如果子線程未完成,則主線程會等待子線程完成後再退出。但是有時候我們需要的是只要主線程

         完成了,不管子線程是否完成,都要和主線程一起退出,這時就可以 用setDaemon方法啦‘‘‘

這麽看來,是不是當要執行多個線程,是不是都可以用Threading來解決呢?
其實並不是,對於計算密集型任務,Python的多線程並沒有用。由於GIL的存在在,一個線程擁有了解釋器的訪問權之後,其他的所有線程都必須等待它釋放解釋器的訪問權,即使這些線程的下一條指令並不會互相影響。
因此Python並不能達到一個並發的效果,同一時間只能運行一個線程,所以對於計算密集型任務,多個線程同時啟動,CPU就需要頻繁的來回切換,這樣就加入了大量的切換時間。而串行的方式則只需要切換少數的幾次,
因此對於計算密集型任務,Python的多線程並沒有用,而對於上面的IO密集型任務,Python的多線程是有意義的。

那麽Python有沒有使用多核的方法呢? 答案是可以的,但只能是開多個進程來實現,那樣弊端也顯而易見,會增大資源開銷而且進程間相互的切換也會非常復雜。
解決的著重點:協程+多進程/ IO多路復用

並發編程/GIL