這篇文章主要介紹關(guān)于Python中線程、進(jìn)程、協(xié)程的簡(jiǎn)介,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:做網(wǎng)站、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的卓資網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
一、線程(Thread)
1、定義:線程是操作系統(tǒng)能進(jìn)行運(yùn)算調(diào)度的最小單位,它包含在進(jìn)程中,是進(jìn)程的實(shí)際運(yùn)作單位,一條線程是進(jìn)程中一個(gè)單一順序的控制流,一個(gè)進(jìn)程中可以并發(fā)多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù)。簡(jiǎn)單理解:線程是一系列指令的集合,操作系統(tǒng)通過(guò)這些指令調(diào)用硬件。
2、同一個(gè)線程中的所有線程共享同一個(gè)內(nèi)存空間資源,
二、進(jìn)程(Progress)
1、定義:一個(gè)程序?qū)Ω髻Y源管理和調(diào)用的集合就是進(jìn)程,比如QQ對(duì)網(wǎng)卡、內(nèi)存、硬盤的調(diào)度和管理。對(duì)于操作系統(tǒng)來(lái)說(shuō),某一個(gè)進(jìn)程是統(tǒng)一的整體。進(jìn)程操作CPU就要先創(chuàng)建一個(gè)線程。進(jìn)程本身是一個(gè)資源集合,執(zhí)行需要靠線程。
三、線程和進(jìn)程的區(qū)別
1、同個(gè)進(jìn)程的線程之間共享內(nèi)存空間,包括數(shù)據(jù)交換和通信,但不同進(jìn)程之間的內(nèi)存是獨(dú)立的
2、子進(jìn)程是克隆了一份父進(jìn)程的數(shù)據(jù),子進(jìn)程之間是互相獨(dú)立的,不能互相訪問(wèn),數(shù)據(jù)也不能共享。
3、兩個(gè)進(jìn)程要通信,必須通過(guò)一個(gè)中間進(jìn)程代理來(lái)實(shí)現(xiàn)。
4、一個(gè)線程可以操作同一個(gè)進(jìn)程中的其他線程,但是進(jìn)程只能操作子進(jìn)程
5、對(duì)主線程的修改,可能會(huì)影響到其他的子線程,因?yàn)樗麄児蚕韮?nèi)存數(shù)據(jù),但對(duì)主進(jìn)程的修改,不會(huì)影響其他子進(jìn)程。
四、多線程的代碼:
import threading import time class MyThread(threading.Thread): """ # 用自定義一個(gè)子類的方式來(lái)啟動(dòng)線程 """ def __init__(self, n): super(MyThread, self).__init__() self.n = n def run(self): print("你好,%s" % self.n) time.sleep(2) start_time = time.time() thread_list = [] # 啟動(dòng)50個(gè)線程 for i in range(50): t1 = MyThread("t%s" % i) t1.start() thread_list.append(t1) # 等待所有線程執(zhí)行完畢后主線程再繼續(xù)執(zhí)行 for i in thread_list: i.join() print("總共執(zhí)行時(shí)間:%s" % float(time.time() - start_time))
五、全局解釋器鎖(GIL)
1、定義:GIL 是最流行的 CPython 解釋器(平常稱為 Python)中的一個(gè)技術(shù)術(shù)語(yǔ),中文譯為全局解釋器鎖,其本質(zhì)上類似操作系統(tǒng)的 Mutex(即互斥鎖,意思是我修改的時(shí)候你不能修改,也就是鎖的意思)
2、功能:在 CPython 解釋器中執(zhí)行的每一個(gè) Python 線程,都會(huì)先鎖住自己,以阻止別的線程執(zhí)行,這樣在同個(gè)時(shí)間一個(gè)CPU只執(zhí)行一個(gè)線程。當(dāng)然,CPython 不可能容忍一個(gè)線程一直獨(dú)占解釋器,check interval 機(jī)制會(huì)在一個(gè)時(shí)間段后釋放前面一個(gè)線程的全局鎖執(zhí)行下一個(gè)線程,以達(dá)到輪流執(zhí)行線程的目的。這樣一來(lái),用戶看到的就是“偽”并行,即 Python 線程在交替執(zhí)行,來(lái)模擬真正并行的線程。
3、CPython 引進(jìn) GIL,可以最大程度上規(guī)避類似內(nèi)存管理這樣復(fù)雜的競(jìng)爭(zhēng)風(fēng)險(xiǎn)問(wèn)題,有了 GIL,并不意味著無(wú)需去考慮線程安全,因?yàn)榧幢?GIL 僅允許一個(gè) Python 線程執(zhí)行,但別忘了 Python 還有 check interval 這樣的搶占機(jī)制。所以就要引入線程鎖的機(jī)制,保證同個(gè)時(shí)間只有一個(gè)線程修改數(shù)據(jù)。
4、線程鎖的代碼如下
import threading import time num = 0 lock_obj = threading.Lock() def run(): # 申請(qǐng)鎖,使別的線程進(jìn)不來(lái) lock_obj.acquire() global num time.sleep(1.1) num = num + 1 # 解鎖,解鎖后別的線程可以進(jìn)來(lái) lock_obj.release() t_list = [] start_time = time.time() # 啟動(dòng)1000個(gè)線程 for i in range(100): t1 = threading.Thread(target=run) t1.start() t_list.append(t1) for i in t_list: i.join() time.sleep(3) print("num:%d" % num) print("time:%f" % float(time.time() - start_time))
六、遞歸鎖:
1、定義:一個(gè)鎖套另外一個(gè)鎖,形成鎖止循環(huán),這種情況就要用到遞歸鎖RLOCK
import threading, time def run1(): print("grab the first part data") lock.acquire() global num num += 1 lock.release() return num def run2(): print("grab the second part data") lock.acquire() global num2 num2 += 1 lock.release() return num2 def run3(): lock.acquire() res = run1() print('--------between run1 and run2-----') res2 = run2() lock.release() print(res, res2) num, num2 = 0, 0 # 這里如果用Lock()就會(huì)無(wú)限循環(huán),找不到具體用哪個(gè)鑰匙打開鎖,如果用RLock就不會(huì),如果又多重鎖嵌套的情況一定要用遞歸鎖 lock = threading.Lock() for i in range(1): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print("當(dāng)前活躍的線程數(shù):",threading.active_count()) else: print('----all threads done---') print("打印num和num2:",num, num2)
七、信號(hào)量(Semaphore)
1、允許同時(shí)間最多幾個(gè)線程進(jìn)入執(zhí)行,每出來(lái)一個(gè)進(jìn)去一個(gè),同時(shí)保持預(yù)先設(shè)置的線程最大允許數(shù)量。
import threading, time def run(n): semaphore.acquire() time.sleep(1) print("run the thread: %s\n" % n) semaphore.release() if __name__ == '__main__': semaphore = threading.BoundedSemaphore(5) # 最多允許5個(gè)線程同時(shí)運(yùn)行 for i in range(22): t = threading.Thread(target=run, args=(i,)) t.start() while threading.active_count() != 1: pass # print threading.active_count() else: print('----all threads done---') #print(num)
八、事件(Event):
1、定義:通過(guò)標(biāo)識(shí)位和狀態(tài),來(lái)實(shí)現(xiàn)線程之間的交互。簡(jiǎn)單說(shuō),就是一個(gè)標(biāo)志位,只有兩種狀態(tài),一種是設(shè)置(Event.set()),一直是沒有設(shè)置(Event.clear())。
2、以下代碼實(shí)現(xiàn)一個(gè)簡(jiǎn)單事件,一個(gè)線程控制紅綠燈,另外一個(gè)線程控制車子,當(dāng)紅綠燈是紅色的時(shí)候,車子停止,綠的時(shí)候,車子行駛的效果
import time import threading event = threading.Event() def lighter(): count = 0 event.set() # 剛開始的標(biāo)識(shí)位先設(shè)置綠燈 while True: if 5 < count < 10: # 改成紅燈 event.clear() # 把標(biāo)志位清了 print("\033[41;1mred light is on....\033[0m") elif count > 10: event.set() # 變綠燈 count = 0 else: print("\033[42;1mgreen light is on....\033[0m") time.sleep(1) count += 1 def car(name): while True: if event.is_set(): # 代表綠燈 print("[%s] running..." % name) time.sleep(1) else: print("[%s] sees red light , waiting...." % name) event.wait() print("\033[34;1m[%s] green light is on, start going...\033[0m" % name) light = threading.Thread(target=lighter, ) light.start() car1 = threading.Thread(target=car, args=("Tesla",)) car1.start()
3、Event類還有兩個(gè)方法,wait()等待被設(shè)定,isset()判斷是否被設(shè)定
以上是關(guān)于Python中線程、進(jìn)程、協(xié)程的簡(jiǎn)介的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!