計(jì)算機(jī)有5大基本組成部分,運(yùn)算器,控制器,存儲(chǔ)器,輸入和輸出。運(yùn)算器和控制器封裝到一起,加上寄存器組和cpu內(nèi)部總線構(gòu)成中央處理器(CPU)。cpu的根本任務(wù),就是執(zhí)行指令,對(duì)計(jì)算機(jī)來說,都是0,1組成的序列,cpu從邏輯上可以劃分為3個(gè)模塊:控制單元、運(yùn)算單元和存儲(chǔ)單元。這三個(gè)部分由cpu總線連接起來。
CPU的運(yùn)行原理就是:控制單元在時(shí)序脈沖的作用下,將指令計(jì)數(shù)器里所指向的指令地址(這個(gè)地址是在內(nèi)存里的)送到地址總線上去,然后CPU將這個(gè)地址里的指令讀到指令寄存器進(jìn)行譯碼。對(duì)于執(zhí)行指令過程中所需要用到的數(shù)據(jù),會(huì)將數(shù)據(jù)地址也送到地址總線,然后CPU把數(shù)據(jù)讀到CPU的內(nèi)部存儲(chǔ)單元(就是內(nèi)部寄存器)暫存起來,最后命令運(yùn)算單元對(duì)數(shù)據(jù)進(jìn)行處理加工。周而復(fù)始,一直這樣執(zhí)行下去。
并發(fā):并發(fā)當(dāng)有多個(gè)線程在操作時(shí),如果系統(tǒng)只有一個(gè)CPU,則它根本不可能真正同時(shí)進(jìn)行一個(gè)以上的線程,它只能把CPU運(yùn)行時(shí)間劃分成若干個(gè)時(shí)間段,再將時(shí)間 段分配給各個(gè)線程執(zhí)行,在一個(gè)時(shí)間段的線程代碼運(yùn)行時(shí),其它線程處于掛起狀。.這種方式我們稱之為并發(fā)(Concurrent)。
并行:當(dāng)系統(tǒng)有一個(gè)以上CPU時(shí),則線程的操作有可能非并發(fā)。當(dāng)一個(gè)CPU執(zhí)行一個(gè)線程時(shí),另一個(gè)CPU可以執(zhí)行另一個(gè)線程,兩個(gè)線程互不搶占CPU資源,可以同時(shí)進(jìn)行,這種方式我們稱之為并行(Parallel)。
并發(fā)與并行的區(qū)別:
多進(jìn)程是各個(gè)并行任務(wù)之間“不使用“共同的內(nèi)存空間;而多線程的各個(gè)并行任務(wù)”使用“共同的內(nèi)存空間。
(1)多進(jìn)程Python 全局解釋器鎖或GIL,簡單來說,是一個(gè)互斥鎖(或鎖),它只允許一個(gè)線程控制 Python 解釋器。這意味著在任何時(shí)間點(diǎn)都只能有一個(gè)線程處于執(zhí)行狀態(tài)。執(zhí)行單線程程序的開發(fā)人員看不到 GIL 的影響,但它可能是 CPU 密集型和多線程代碼中的性能瓶頸。由于即使在具有多個(gè) CPU 內(nèi)核的多線程架構(gòu)中,GIL 也只允許一次執(zhí)行一個(gè)線程,因此 GIL 被稱為 Python 的“臭名昭著”的特性,但是它確實(shí)為Python內(nèi)存處理提供了方便。
如果一個(gè)對(duì)象同時(shí)被多個(gè)線程來引用,那么引用計(jì)數(shù)可能同時(shí)增加或減少,每個(gè)線程按照自己的方式進(jìn)行計(jì)數(shù),對(duì)象在整個(gè)內(nèi)存中的引用變得十分混亂,很容易造成內(nèi)存泄漏或者其他很多不可預(yù)見的Bug。一個(gè)解決辦法給就是每個(gè)線程都給引用計(jì)數(shù)加一個(gè)鎖,阻止別人修改,不過這樣會(huì)造成鎖死現(xiàn)象(比如一個(gè)對(duì)象有多個(gè)鎖時(shí)),另外,大量的資源會(huì)浪費(fèi)在加鎖解鎖的過程了,嚴(yán)重拖慢了程序運(yùn)行速度。
這個(gè)時(shí)候,就需要一個(gè)統(tǒng)一來管理引用計(jì)數(shù)的機(jī)制,以確保對(duì)象引用計(jì)數(shù)準(zhǔn)確、安全。全局解釋器鎖就是用來處理這種情況的。它既避免了不同線程帶來的引用計(jì)數(shù)混亂,又避免了過多線程鎖帶來的死鎖和運(yùn)行效率低的問題。雖然全局解釋器鎖解決了對(duì)象引用計(jì)數(shù)的問題,但隨之而來的是,很多CPU密集型任務(wù)在全局解釋器鎖的作用下,實(shí)際上變成了單線程,不能充分發(fā)揮CPU的算力,影響程序速度。
全局解釋器鎖并不是Python獨(dú)有的,其他一些語言,比如Ruby也存在全局解釋器鎖。還有一些語言沒有使用引用計(jì)數(shù)的方式來管理內(nèi)容,而是使用垃圾回收機(jī)制(GC)來管理內(nèi)存。雖然這樣避免了全局解釋器鎖,但是在單線程處理上,GC并不占有優(yōu)勢。
全局解釋器鎖對(duì)多線程的影響
進(jìn)程就是運(yùn)行著的程序。寫的python程序(或者其他應(yīng)用程序比如畫筆、qq等),運(yùn)行起來,就稱之為一個(gè)進(jìn)程;在windows下面打開任務(wù)管理器,里面顯示了當(dāng)前系統(tǒng)上運(yùn)行著的進(jìn)程。這些程序還沒有運(yùn)行的時(shí)候,它們的程序代碼文件存儲(chǔ)在磁盤中,就是那些擴(kuò)展名為 .exe 文件。雙擊它們,這些 .exe 文件就被os加載到內(nèi)存中,運(yùn)行起來,成為進(jìn)程。
進(jìn)程池:可以提供指定數(shù)量的進(jìn)程給用戶使用,即當(dāng)有新的請(qǐng)求提交到進(jìn)程池中時(shí),如果池未滿,則會(huì)創(chuàng)建一個(gè)新的進(jìn)程用來執(zhí)行該請(qǐng)求;反之,如果池中的進(jìn)程數(shù)已經(jīng)達(dá)到規(guī)定大值,那么該請(qǐng)求就會(huì)等待,只要池中有進(jìn)程空閑下來,該請(qǐng)求就能得到執(zhí)行。
7.線程池系統(tǒng)中每個(gè)進(jìn)程里面至少包含一個(gè) 線程 。線程是操作系統(tǒng)創(chuàng)建的,每個(gè)線程對(duì)應(yīng)一個(gè)代碼執(zhí)行的數(shù)據(jù)結(jié)構(gòu),保存了代碼執(zhí)行過程中的重要的狀態(tài)信息。沒有線程,操作系統(tǒng)沒法管理和維護(hù) 代碼運(yùn)行的狀態(tài)信息。所以沒有創(chuàng)建線程之前,操作系統(tǒng)是不會(huì)執(zhí)行我們的代碼的。
8.同步和異步在一個(gè)進(jìn)程中,不同子線程負(fù)責(zé)不同的任務(wù),t1子線程負(fù)責(zé)獲取到數(shù)據(jù),t2子線程負(fù)責(zé)把數(shù)據(jù)保存的本地,那么他們之間的通信使用Queue來完成。因?yàn)樵僖粋€(gè)進(jìn)程中,數(shù)據(jù)變量是共享的,即多個(gè)子線程可以對(duì)同一個(gè)全局變量進(jìn)行操作修改,Queue是加了鎖的安全消息隊(duì)列。
Python的Queue隊(duì)列,主要用于多生產(chǎn)者和消費(fèi)者模式下的隊(duì)列實(shí)現(xiàn),特別適合多線程時(shí)的消息交換。通過使用隊(duì)列,把生產(chǎn)者和消費(fèi)者分解開來,作為其中的中間件,比如生產(chǎn)者產(chǎn)生一個(gè)數(shù)據(jù),然后放到queue隊(duì)列中,queue隊(duì)列在把這個(gè)數(shù)據(jù)放到消費(fèi)者線程中。使用單線程不必用隊(duì)列,但是隊(duì)列對(duì)于多線程來說是不可或缺的。
10.線程同步如果沒有控制多個(gè)線程對(duì)同一資源的訪問,對(duì)數(shù)據(jù)造成破壞,使得線程運(yùn)行的結(jié)果不可預(yù)期。這種現(xiàn)象稱為“線程不安全”。同步就是協(xié)同步調(diào),按預(yù)定的先后次序進(jìn)行運(yùn)行。
"同"字從字面上容易理解為一起動(dòng)作,其實(shí)不是,"同"字應(yīng)是指協(xié)同、協(xié)助、互相配合。如進(jìn)程、線程同步,可理解為進(jìn)程或線程A和B一塊配合,A執(zhí)行到一定程度時(shí)要依靠B的某個(gè)結(jié)果,于是停下來,示意B運(yùn)行;B依言執(zhí)行,再將結(jié)果給A;A再繼續(xù)操作。
實(shí)現(xiàn)線程同步的方式可以是:
生產(chǎn)者消費(fèi)者模型具體來講,就是在一個(gè)系統(tǒng)中,存在生產(chǎn)者和消費(fèi)者兩種角色,他們通過內(nèi)存緩沖區(qū)進(jìn)行通信,生產(chǎn)者生產(chǎn)消費(fèi)者需要的資料,消費(fèi)者消耗數(shù)據(jù)或者資料。
舉一個(gè)寄信的例子,假設(shè)要寄一封信,大致過程如下:
Python 中,構(gòu)造線程的時(shí)候,可以設(shè)置daemon屬性,這個(gè)屬性必須再start()方法前設(shè)置好。線程daemon屬性,如果設(shè)定就是用戶的設(shè)置,否則就取當(dāng)前線程的daemon值。主線程是non-daemon線程,即daemon = False。線程具有一個(gè)daemon屬性,可以手動(dòng)設(shè)置為True或者False,也可以不設(shè)置,則取默認(rèn)值為None。
如果除主線程之外還有non-daemon線程的時(shí)候,主線程退出時(shí),也不會(huì)殺掉所有daemon線程,直到所有non-daemon線程全部結(jié)束,如果還有daemon線程,主線程需要退出,會(huì)結(jié)束所有daemon線程,程序退出。
13.鎖和共享內(nèi)存【多線程、多進(jìn)程涉及讀寫必須要用鎖,一定要用】
(1)多線程的線程鎖①死鎖問題和解決
如果多個(gè)線程要調(diào)用多個(gè)現(xiàn)象,而A線程調(diào)用A鎖占用了A對(duì)象,B線程調(diào)用了B鎖占用了B對(duì)象,A線程不能調(diào)用B對(duì)象,B線程不能調(diào)用A對(duì)象,于是一直等待。這就造成了線程“死鎖”。Threading模塊中,也有一個(gè)類,RLock,稱之為可重入鎖。該鎖對(duì)象內(nèi)部維護(hù)著一個(gè)Lock和一個(gè)counter對(duì)象。counter對(duì)象記錄了acquire的次數(shù),使得資源可以被多次require。最后,當(dāng)所有RLock被release后,其他線程才能獲取資源。在同一個(gè)線程中,RLock.acquire可以被多次調(diào)用,利用該特性,可以解決部分死鎖問題
②當(dāng)多個(gè)線程同時(shí)訪問一個(gè)數(shù)據(jù)時(shí),需加鎖,排隊(duì)變成單線程一個(gè)一個(gè)執(zhí)行,避免出錯(cuò)。
③加鎖避免并發(fā)導(dǎo)致邏輯出錯(cuò)。
④每當(dāng)一個(gè)線程a要訪問共享數(shù)據(jù)時(shí),必須先獲得鎖定;如果已經(jīng)有別的線程b獲得鎖定了,那么就讓線程a暫停,也就是同步阻塞;等到線程b訪問完畢,釋放鎖以后,再讓線程a繼續(xù)。
⑤同一時(shí)刻只允許一個(gè)線程操作該數(shù)據(jù),可以保證數(shù)據(jù)安全。 線程鎖用于鎖定資源,可以同時(shí)使用多個(gè)鎖,當(dāng)需要獨(dú)占某一資源時(shí),任何一個(gè)鎖都可以鎖這個(gè)資源。
⑥將一段代碼鎖住,一旦獲得鎖權(quán)限,除非釋放線程鎖,否則其他代碼都無法獲得鎖權(quán)限。
(2)多進(jìn)程的進(jìn)程鎖①很多時(shí)候,需要在多個(gè)進(jìn)程中同時(shí)寫一個(gè)文件,如果不加鎖機(jī)制,就會(huì)導(dǎo)致寫文件錯(cuò)亂。
②誰先搶到鎖誰先執(zhí)行,等到該進(jìn)程執(zhí)行完成后,其它進(jìn)程再搶鎖執(zhí)行。
③python多進(jìn)程編程使用進(jìn)程池非常的方便管理進(jìn)程,但是有時(shí)候子進(jìn)程之間會(huì)搶占一些獨(dú)占資源,比如consol或者比如日志文件的寫入權(quán)限,這樣的時(shí)候我們一般需要共享一個(gè)Lock來對(duì)獨(dú)占資源加鎖。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)站題目:1.1異步相關(guān)概念:初步了解-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://jinyejixie.com/article38/eehsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、搜索引擎優(yōu)化、定制開發(fā)、網(wǎng)站設(shè)計(jì)、靜態(tài)網(wǎng)站、服務(wù)器托管
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容