摘要:也提供多線程支持,而且中的線程并非是模擬出來(lái)的多線程,而是系統(tǒng)級(jí)別的標(biāo)準(zhǔn)庫(kù)提供了兩個(gè)模塊和。同一個(gè)變量,線程則會(huì)互相共享。例如多個(gè)線程對(duì)銀行中的某一個(gè)賬戶進(jìn)行操作。但是實(shí)際情況是隨意切換線程。說(shuō)到的多線程編程,就會(huì)繞不過(guò)。
該文章參考了http://www.liaoxuefeng.com/wi... 廖雪峰的教程。
一個(gè)進(jìn)程至少有一個(gè)線程。
Python也提供多線程支持,而且Python中的線程并非是模擬出來(lái)的多線程,而是系統(tǒng)級(jí)別的Posix Thread.
Python標(biāo)準(zhǔn)庫(kù)提供了兩個(gè)模塊thread和threading。前者是低級(jí)庫(kù),后者是高級(jí)庫(kù)。高級(jí)庫(kù)是對(duì)低級(jí)庫(kù)的封裝。
通常情況下,我們只需要使用threading高級(jí)庫(kù)就可以了。
我們只需要?jiǎng)?chuàng)建threading.Thread類(lèi),并傳入一個(gè)需要線程執(zhí)行的函數(shù)作為target即可。
import threading import time def loop(): count = 1 while count < 4: print "Hello" time.sleep(1) count += 1 if __name__ == "__main__": thread = threading.Thread(target=loop, name="LoopThread") thread.start() thread.join() current_thread = threading.current_thread() print current_thread.getName() print "LoopThread Ended"
上述代碼主進(jìn)程默認(rèn)會(huì)創(chuàng)建一個(gè)主線程。
上面的代碼中,我們用到了多個(gè)函數(shù)。
join()函數(shù):即讓主線程序等待子線程完成后繼續(xù)。
current_thread()函數(shù):獲取當(dāng)前線程的實(shí)例。
Lock 鎖同一個(gè)變量,進(jìn)程會(huì)拷貝一份存于各個(gè)進(jìn)程中,互不影響。
同一個(gè)變量,線程則會(huì)互相共享。這就會(huì)帶來(lái)一些問(wèn)題。因?yàn)閏pu對(duì)線程是隨意切換的。那么如果一個(gè)線程對(duì)某一個(gè)變量進(jìn)行多步cpu操作的時(shí)候,如果不加鎖,那么可能會(huì)在線程進(jìn)行到一半的時(shí)候,會(huì)被切換到其他線程,從而使得操作變亂。
一個(gè)典型的例子是“一存一取”的場(chǎng)景。
例如多個(gè)線程對(duì)銀行中的某一個(gè)賬戶進(jìn)行操作。一個(gè)線程需要對(duì)賬戶進(jìn)行一存一取某一個(gè)金額的操作才會(huì)讓賬戶平衡。
但是多個(gè)線程對(duì)該賬戶進(jìn)行操作的時(shí)候,且它們操作的金額經(jīng)常是不一樣的,那么最終的賬戶很可能是不平衡的。
thread 1: -100 thread 1: +100 thread 1: -100 thread 1: +100 thread 2: -200 thread 2: +200 thread 2: -200 thread 2: +200
上述描述了兩個(gè)線程按順序互補(bǔ)干擾地對(duì)某一個(gè)賬戶進(jìn)行操作。
但是實(shí)際情況是cpu隨意切換線程。上述操作是打亂的,例如
thread 1: -100 thread 2: -200 thread 2: +200 ...
此時(shí),我們發(fā)現(xiàn)賬戶并不是平衡的。
如果解決呢?我們需要對(duì)每一個(gè)thread的一存一取操作加一把鎖。即改賬戶變量必須是讓一個(gè)線程先進(jìn)行完整的一存一取操作后,才能被其他線程所操作。
我們可以將要上鎖的代碼包裹起來(lái),即:
lock.acquire() num = num + n num = num - n print num lock.release()
當(dāng)然,lock可以對(duì)資源的獲取和釋放,那么我們也可以用with關(guān)鍵字。
with lock: num = num + n num = num - n print num死鎖 deadlock
死鎖的發(fā)生往往是兩個(gè)線程各自占用了對(duì)方所需要用到的資源而都在等待對(duì)方釋放資源而造成的。
遇見(jiàn)死鎖后,程序則會(huì)一直暫停在那里。直到系統(tǒng)將它們關(guān)閉。
說(shuō)到Python的多線程編程,就會(huì)繞不過(guò)GIL。那么GIL又是什么鬼呢?
GIL據(jù)說(shuō)是Python中hardest的問(wèn)題,想要徹底了解GIL,必須要對(duì)操作系統(tǒng)設(shè)計(jì)、多線程編程、C語(yǔ)言、解釋器設(shè)計(jì)和CPython解釋器的實(shí)現(xiàn)有著非常徹底的理解。
據(jù)廖雪峰中的教程中描述:
Python中的線程雖然是真正的線程,但是解釋器執(zhí)行代碼的時(shí)候,會(huì)有一個(gè)GIL鎖(Global Interpreter Lock). 任何Python線程執(zhí)行前,必須先獲得GIL鎖。然后,每執(zhí)行100條字節(jié)碼,解釋器就會(huì)自動(dòng)釋放GIL鎖,讓別的線程有機(jī)會(huì)執(zhí)行。這個(gè)GIL全局鎖實(shí)際上把所有線程的執(zhí)行代碼都給上了鎖。因此,多線程在Python中只能交替進(jìn)行,即使100個(gè)線程跑在100核CPU上,也只能用到1個(gè)核心。
GIL是Python解釋器設(shè)計(jì)的歷史遺留問(wèn)題,通常我們用的解釋器是官方實(shí)現(xiàn)徹底CPython。
更多關(guān)于GIL設(shè)計(jì)的歷史淵源,可以閱讀:
http://cenalulu.github.io/pyt...
http://www.oschina.net/transl...
那么是不是Python就是不能利用多核處理器任務(wù)了呢?我們之前學(xué)到過(guò)多進(jìn)程編程,每一個(gè)進(jìn)程都有一個(gè)獨(dú)立的GIL鎖,各進(jìn)程互不影響。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/38366.html
摘要:最近看前端都展開(kāi)了幾場(chǎng)而我大知乎最熱語(yǔ)言還沒(méi)有相關(guān)。有關(guān)書(shū)籍的介紹,大部分截取自是官方介紹。但從開(kāi)始,標(biāo)準(zhǔn)庫(kù)為我們提供了模塊,它提供了和兩個(gè)類(lèi),實(shí)現(xiàn)了對(duì)和的進(jìn)一步抽象,對(duì)編寫(xiě)線程池進(jìn)程池提供了直接的支持。 《流暢的python》閱讀筆記 《流暢的python》是一本適合python進(jìn)階的書(shū), 里面介紹的基本都是高級(jí)的python用法. 對(duì)于初學(xué)python的人來(lái)說(shuō), 基礎(chǔ)大概也就夠用了...
摘要:試想,在多線程服務(wù)器中,多個(gè)線程同時(shí)處理不同客戶端發(fā)送的不同請(qǐng)求時(shí),每個(gè)線程看到的對(duì)象必然不同。多線程服務(wù)器會(huì)創(chuàng)建一個(gè)線程池,再?gòu)木€程池中選擇一個(gè)線程用于處理接收到的請(qǐng)求。 框架 Django flask flask是一個(gè)輕量的web開(kāi)發(fā)應(yīng)用示例開(kāi)發(fā)一個(gè)小應(yīng)用 from flask import Flask app = Flask(__name__) @app.route(/) d...
摘要:為了避免改亂為,我們?cè)谇懊嬉呀?jīng)提到說(shuō)要加鎖。僅供一個(gè)線程使用,線程間相互不影響。例如下列程序中函數(shù)中定義的變量就是局部變量。所有綁定的參數(shù)都是線程隔離的。下面展示一下代碼創(chuàng)建一個(gè)全局的對(duì)象初始化一個(gè)線程內(nèi)變量,該變量線程間互不影響。 我們?cè)诰帉?xiě)多線程程序的時(shí)候,往往會(huì)遇到兩種類(lèi)型的變量。 一種是全局變量,多個(gè)線程共享。為了避免改亂為,我們?cè)谇懊嬉呀?jīng)提到說(shuō)要加鎖。 一種是局部變量。僅供...
摘要:首發(fā)于我的博客線程池進(jìn)程池網(wǎng)絡(luò)編程之同步異步阻塞非阻塞后端掘金本文為作者原創(chuàng),轉(zhuǎn)載請(qǐng)先與作者聯(lián)系。在了解的數(shù)據(jù)結(jié)構(gòu)時(shí),容器可迭代對(duì)象迭代器使用進(jìn)行并發(fā)編程篇二掘金我們今天繼續(xù)深入學(xué)習(xí)。 Python 算法實(shí)戰(zhàn)系列之棧 - 后端 - 掘金原文出處: 安生??? 棧(stack)又稱之為堆棧是一個(gè)特殊的有序表,其插入和刪除操作都在棧頂進(jìn)行操作,并且按照先進(jìn)后出,后進(jìn)先出的規(guī)則進(jìn)行運(yùn)作。 如...
摘要:開(kāi)頭正式開(kāi)啟我入職的里程,現(xiàn)在已是工作了一個(gè)星期了,這個(gè)星期算是我入職的過(guò)渡期,算是知道了學(xué)校生活和工作的差距了,總之,盡快習(xí)慣這種生活吧。當(dāng)時(shí)是看的廖雪峰的博客自己也用做爬蟲(chóng)寫(xiě)過(guò)幾篇博客,不過(guò)有些是在前人的基礎(chǔ)上寫(xiě)的。 showImg(https://segmentfault.com/img/remote/1460000010867984); 開(kāi)頭 2017.08.21 正式開(kāi)啟我...
閱讀 3476·2021-11-25 09:43
閱讀 2624·2021-09-22 15:54
閱讀 597·2019-08-30 15:55
閱讀 982·2019-08-30 15:55
閱讀 2007·2019-08-30 15:55
閱讀 1748·2019-08-30 15:53
閱讀 3476·2019-08-30 15:52
閱讀 2046·2019-08-30 12:55