python真正的多線程
Ⅰ 書聲琅琅教育旗下智圭谷:如何在python中實現多線程
python主要是通過thread和threading這兩個模塊來實現多線程支持。
python的thread模塊是比較底層的模塊,python的threading模塊是對thread做了一些封裝,可以更加方便的被使用。但是python(cpython)由於GIL的存在無法使用threading充分利用CPU資源,如果想充分發揮多核CPU的計算能力需要使用multiprocessing模塊(Windows下使用會有諸多問題)。
python3.x中已經摒棄了Python2.x中採用函數式thread模塊中的start_new_thread()函數來產生新線程方式。python3.x中通過threading模塊創建新的線程有兩種方法:
1、通過threading.Thread(Target=executable Method)-即傳遞給Thread對象一個可執行方法(或對象)
2、繼承threading.Thread定義子類並重寫run()方法。第二種方法中,唯一必須重寫的方法是run()。
了解更多python知識,0基礎新手python在線學習就上智圭谷-書聲琅琅教育旗下高端IT教育品牌,專注python語言領域
Ⅱ 什麼是線程(多線程),Python多線程的好處
幾乎所有的操作系統都支持同時運行多個任務,一個任務通常就是一個程序,每一個運行中的程序就是一個進程。當一個程序運行時,內部可能包含多個順序執行流,每一個順序執行流就是一個線程。
線程和進程
幾乎所有的操作系統都支持進程的概念,所有運行中的任務通常對應一個進程(Process)。當一個程序進入內存運行時,即變成一個進程。進程是處於運行過程中的程序,並且具有一定的獨立功能。進程是系統進行資源分配和調度的一個獨立單位。
一般而言,進程包含如下三個特徵:
獨立性:進程是系統中獨立存在的實體,它可以擁有自己的獨立的資源,每一個進程都擁有自己的私有的地址空間。在沒有經過進程本身允許的情況下,一個用戶進程不可以直接訪問其他進程的地址空間。
動態性:進程與程序的區別在於,程序只是一個靜態的指令集合,而進程是一個正在系統中活動的指令集合。在進程中加入了時間的概念。進程具有自己的生命周期和各種不同的狀態,在程序中是沒有這些概念的。
並發性:多個進程可以在單個處理器上並發執行,多個進程之間不會互相影響。
並發(Concurrency)和並行(Parallel)是兩個概念,並行指在同一時刻有多條指令在多個處理器上同時執行;並發才旨在同一時刻只能有一條指令執行,但多個進程指令被快速輪換執行,使得在宏觀上具有多個進程同時執行的效果。
大部分操作系統都支持多進程並發執行,現代的操作系統幾乎都支持同時執行多個任務。例如,程序員一邊開著開發工具在寫程序,一邊開著參考手冊備查,同時還使用電腦播放音樂……除此之外,每台電腦運行時還有大量底層的支撐性程序在運行……這些進程看上去像是在同時工作。
但事實的真相是,對於一個 CPU 而言,在某個時間點它只能執行一個程序。也就是說,只能運行一個進程,CPU 不斷地在這些進程之間輪換執行。那麼,為什麼用戶感覺不到任何中斷呢?
這是因為相對人的感覺來說,CPU 的執行速度太快了(如果啟動的程序足夠多,則用戶依然可以感覺到程序的運行速度下降了)。所以,雖然 CPU 在多個進程之間輪換執行,但用戶感覺到好像有多個進程在同時執行。
現代的操作系統都支持多進程的並發執行,但在具體的實現細節上可能因為硬體和操作系統的不同而採用不同的策略。比較常用的策略有:
共用式的多任務操作策略,例如 Windows 3.1 和 Mac OS 9 操作系統採用這種策略;
搶占式的多任務操作策略,其效率更高,目前操作系統大多採用這種策略,例如 Windows NT、Windows 2000 以及 UNIX/Linux 等操作系統。
多線程則擴展了多進程的概念,使得同一個進程可以同時並發處理多個任務。線程(Thread)也被稱作輕量級進程(Lightweight Process),線程是進程的執行單元。就像進程在操作系統中的地位一樣,線程在程序中是獨立的、並發的執行流。
當進程被初始化後,主線程就被創建了。對於絕大多數的應用程序來說,通常僅要求有一個主線程,但也可以在進程內創建多個順序執行流,這些順序執行流就是線程,每一個線程都是獨立的。
線程是進程的組成部分,一個進程可以擁有多個線程,一個線程必須有一個父進程。線程可以擁有自己的堆棧、自己的程序計數器和自己的局部變數,但不擁有系統資源,它與父進程的其他線程共享該進程所擁有的全部資源。因為多個線程共享父進程里的全部資源,因此編程更加方便;但必須更加小心,因為需要確保線程不會妨礙同一進程中的其他線程。
線程可以完成一定的任務,可以與其他線程共享父進程中的共享變數及部分環境,相互之間協同未完成進程所要完成的任務。
線程是獨立運行的,它並不知道進程中是否還有其他線程存在。線程的運行是搶占式的,也就是說,當前運行的線程在任何時候都可能被掛起,以便另外一個線程可以運行。
一個線程可以創建和撤銷另一個線程,同一個進程中的多個線程之間可以並發運行。
從邏輯的角度來看,多線程存在於一個應用程序中,讓一個應用程序可以有多個執行部分同時執行,但操作系統無須將多個線程看作多個獨立的應用,對多線程實現調度和管理,以及資源分配。線程的調度和管理由進程本身負責完成。
簡而言之,一個程序運行後至少有一個進程,在一個進程中可以包含多個線程,但至少要包含一個主線程。
歸納起來可以這樣說,操作系統可以同時執行多個任務,每一個任務就是一個進程,進程可以同時執行多個任務,每一個任務就是一個線程。
多線程的好處
線程在程序中是獨立的、並發的執行流。與分隔的進程相比,進程中線程之間的隔離程度要小,它們共享內存、文件句柄和其他進程應有的狀態
因為線程的劃分尺度小於進程,使得多線程程序的並發性高。進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
線程比進程具有更高的性能,這是由於同一個進程中的線程都有共性多個線程共享同一個進程的虛擬空間。線程共享的環境包括進程代碼段、進程的公有數據等,利用這些共享的數據,線程之間很容易實現通信。
操作系統在創建進程時,必須為該進程分配獨立的內存空間,並分配大量的相關資源,但創建線程則簡單得多。因此,使用多線程來實現並發比使用多進程的性能要高得多。
總結起來,使用多線程編程具有如下幾個優點:
進程之間不能共享內存,但線程之間共享內存非常容易。
操作系統在創建進程時,需要為該進程重新分配系統資源,但創建線程的代價則小得多。因此,使用多線程來實現多任務並發執行比使用多進程的效率高。
Python 語言內置了多線程功能支持,而不是單純地作為底層操作系統的調度方式,從而簡化了 Python 的多線程編程。
在實際應用中,多線程是非常有用的。比如一個瀏覽器必須能同時下載多張圖片;一個 Web 伺服器必須能同時響應多個用戶請求;圖形用戶界面(GUI)應用也需要啟動單獨的線程,從主機環境中收集用戶界面事件……總之,多線程在實際編程中的應用是非常廣泛的。
Ⅲ python多線程的幾種方法
Python進階(二十六)-多線程實現同步的四種方式
臨界資源即那些一次只能被一個線程訪問的資源,典型例子就是列印機,它一次只能被一個程序用來執行列印功能,因為不能多個線程同時操作,而訪問這部分資源的代碼通常稱之為臨界區。
鎖機制
threading的Lock類,用該類的acquire函數進行加鎖,用realease函數進行解鎖
import threadingimport timeclass Num:
def __init__(self):
self.num = 0
self.lock = threading.Lock() def add(self):
self.lock.acquire()#加鎖,鎖住相應的資源
self.num += 1
num = self.num
self.lock.release()#解鎖,離開該資源
return num
n = Num()class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item def run(self):
time.sleep(2)
value = n.add()#將num加1,並輸出原來的數據和+1之後的數據
print(self.item,value)for item in range(5):
t = jdThread(item)
t.start()
t.join()#使線程一個一個執行
當一個線程調用鎖的acquire()方法獲得鎖時,鎖就進入「locked」狀態。每次只有一個線程可以獲得鎖。如果此時另一個線程試圖獲得這個鎖,該線程就會變為「blocked」狀態,稱為「同步阻塞」(參見多線程的基本概念)。
直到擁有鎖的線程調用鎖的release()方法釋放鎖之後,鎖進入「unlocked」狀態。線程調度程序從處於同步阻塞狀態的線程中選擇一個來獲得鎖,並使得該線程進入運行(running)狀態。
信號量
信號量也提供acquire方法和release方法,每當調用acquire方法的時候,如果內部計數器大於0,則將其減1,如果內部計數器等於0,則會阻塞該線程,知道有線程調用了release方法將內部計數器更新到大於1位置。
import threadingimport timeclass Num:
def __init__(self):
self.num = 0
self.sem = threading.Semaphore(value = 3) #允許最多三個線程同時訪問資源
def add(self):
self.sem.acquire()#內部計數器減1
self.num += 1
num = self.num
self.sem.release()#內部計數器加1
return num
n = Num()class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item def run(self):
time.sleep(2)
value = n.add()
print(self.item,value)for item in range(100):
Ⅳ python多線程幾種方法實現
Python進階(二十六)-多線程實現同步的四種方式
臨界資源即那些一次只能被一個線程訪問的資源,典型例子就是列印機,它一次只能被一個程序用來執行列印功能,因為不能多個線程同時操作,而訪問這部分資源的代碼通常稱之為臨界區。
鎖機制
threading的Lock類,用該類的acquire函數進行加鎖,用realease函數進行解鎖
import threadingimport timeclass Num:
def __init__(self):
self.num = 0
self.lock = threading.Lock() def add(self):
self.lock.acquire()#加鎖,鎖住相應的資源
self.num += 1
num = self.num
self.lock.release()#解鎖,離開該資源
return num
n = Num()class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item def run(self):
time.sleep(2)
value = n.add()#將num加1,並輸出原來的數據和+1之後的數據
print(self.item,value)for item in range(5):
t = jdThread(item)
t.start()
t.join()#使線程一個一個執行
當一個線程調用鎖的acquire()方法獲得鎖時,鎖就進入「locked」狀態。每次只有一個線程可以獲得鎖。如果此時另一個線程試圖獲得這個鎖,該線程就會變為「blocked」狀態,稱為「同步阻塞」(參見多線程的基本概念)。
直到擁有鎖的線程調用鎖的release()方法釋放鎖之後,鎖進入「unlocked」狀態。線程調度程序從處於同步阻塞狀態的線程中選擇一個來獲得鎖,並使得該線程進入運行(running)狀態。
信號量
信號量也提供acquire方法和release方法,每當調用acquire方法的時候,如果內部計數器大於0,則將其減1,如果內部計數器等於0,則會阻塞該線程,知道有線程調用了release方法將內部計數器更新到大於1位置。
import threadingimport timeclass Num:
def __init__(self):
self.num = 0
self.sem = threading.Semaphore(value = 3) #允許最多三個線程同時訪問資源
def add(self):
self.sem.acquire()#內部計數器減1
self.num += 1
num = self.num
self.sem.release()#內部計數器加1
return num
n = Num()class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item def run(self):
time.sleep(2)
value = n.add()
print(self.item,value)for item in range(100):
Ⅳ python的多線程是真的多線程嗎
簡單地說就是作為可能是僅有的支持多線程的解釋型語言(perl的多線程是殘疾,PHP沒有多線程),Python的多線程是有compromise的,在任意時間只有一個Python解釋器在解釋Python bytecode。
UPDATE:如評論指出,Ruby也是有thread支持的,而且至少Ruby MRI是有GIL的。
如果你的代碼是CPU密集型,多個線程的代碼很有可能是線性執行的。所以這種情況下多線程是雞肋,效率可能還不如單線程因為有context switch
但是:如果你的代碼是IO密集型,多線程可以明顯提高效率。例如製作爬蟲(我就不明白為什麼Python總和爬蟲聯系在一起…不過也只想起來這個例子…),絕大多數時間爬蟲是在等待socket返回數據。這個時候C代碼里是有release GIL的,最終結果是某個線程等待IO的時候其他線程可以繼續執行。
反過來講:你就不應該用Python寫CPU密集型的代碼…效率擺在那裡…
如果確實需要在CPU密集型的代碼里用concurrent,就去用multiprocessing庫。這個庫是基於multi process實現了類multi thread的API介面,並且用pickle部分地實現了變數共享。
再加一條,如果你不知道你的代碼到底算CPU密集型還是IO密集型,教你個方法:
multiprocessing這個mole有一個mmy的sub mole,它是基於multithread實現了multiprocessing的API。
假設你使用的是multiprocessing的Pool,是使用多進程實現了concurrency
from multiprocessing import Pool
如果把這個代碼改成下面這樣,就變成多線程實現concurrency
from multiprocessing.mmy import Pool
兩種方式都跑一下,哪個速度快用哪個就行了。
UPDATE:
剛剛才發現concurrent.futures這個東西,包含ThreadPoolExecutor和ProcessPoolExecutor,可能比multiprocessing更簡單
Ⅵ 請教python如何開啟多線程
可以定義函數把這些代碼放在不同的函數里,然後threading模塊
import threading
th1 = threading.Thread(target=func1, args=(arg1, arg2, ...))
照這樣再定義別的線程,開啟用Thread類的start方法
th1.start(); th2.start(); ...
Ⅶ python 怎麼實現多線程的
線程也就是輕量級的進程,多線程允許一次執行多個線程,Python是多線程語言,它有一個多線程包,GIL也就是全局解釋器鎖,以確保一次執行單個線程,一個線程保存GIL並在將其傳遞給下一個線程之前執行一些操作,也就產生了並行執行的錯覺。
Ⅷ 為什麼說Python沒有真正意義上的多線程
因為python解釋器同一個時間只能使用一個cpu,所以再多的線程還是使用同一個cpu
真正的多線程是充分利用多個cpu的計算能力的
Ⅸ python多線程作用
總結起來,使用多線程編程具有如下幾個優點:
進程之間不能共享內存,但線程之間共享內存非常容易。
操作系統在創建進程時,需要為該進程重新分配系統資源,但創建線程的代價則小得多。因此,使用多線程來實現多任務並發執行比使用多進程的效率高。
Python 語言內置了多線程功能支持,而不是單純地作為底層操作系統的調度方式,從而簡化了 Python 的多線程編程。
在實際應用中,多線程是非常有用的。比如一個瀏覽器必須能同時下載多張圖片;一個 Web 伺服器必須能同時響應多個用戶請求;圖形用戶界面(GUI)應用也需要啟動單獨的線程,從主機環境中收集用戶界面事件……總之,多線程在實際編程中的應用是非常廣泛的。
Ⅹ Python多線程是什麼意思
多線程能讓你像運行一個獨立的程序一樣運行一段長代碼。這有點像調用子進程(subprocess),不過區別是你調用shu的是一個函數或者一個類,而不是獨立的程序。
程基本上是一個獨立執行流程。單個進程可以由多個線程組成。程序中的每個線程都執行特定的任務。例如,當你在電腦上玩游戲時,比如說國際足聯,整個游戲是一個單一的過程。,但它由幾個線程組成,負責播放音樂、接收用戶的輸入、同步運行對手等。所有這些都是單獨的線程,負責在同一個程序中執行這些不同的任務。
每個進程都有一個始終在運行的線程。這是主線。這個主線程實際上創建子線程對象。子線程也由主線程啟動。