互斥鎖
線程是非獨(dú)立的,同一個(gè)進(jìn)程里線程是數(shù)據(jù)共享的,當(dāng)各個(gè)線程訪問(wèn)數(shù)據(jù)資源時(shí)會(huì)出現(xiàn)競(jìng)爭(zhēng)狀態(tài)即:數(shù)據(jù)幾乎同步會(huì)被多個(gè)線程占用,造成數(shù)據(jù)混亂忍饰,即所謂的線程不安全。
為了解決這個(gè)問(wèn)題寺庄, 引入了互斥鎖的概念艾蓝,一個(gè)資源只能被一個(gè)線程執(zhí)行力崇。
壞處: 阻止了多線程并發(fā)執(zhí)行,包含鎖的某段代碼實(shí)際上只能以單線程模式執(zhí)行赢织,效率就大大地下降了
鎖的致命問(wèn)題: 死鎖
死鎖
若干子線程在系統(tǒng)資源競(jìng)爭(zhēng)時(shí)亮靴,都在等待對(duì)方對(duì)某部分資源解除占用狀態(tài),結(jié)果是誰(shuí)也不愿先解鎖于置,互相干等著茧吊,程序無(wú)法執(zhí)行下去,這就是死鎖八毯。
造成死鎖的原因可以概括成三句話:
- 當(dāng)前線程擁有其他線程需要的資源
- 當(dāng)前線程等待其他線程已擁有的資源
- 都不放棄自己擁有的資源
死鎖的產(chǎn)生條件:
- 互斥條件:指進(jìn)程對(duì)所分配到的資源進(jìn)行排它性使用搓侄,即在一段時(shí)間內(nèi)某資源只由一個(gè)進(jìn)程占用。如果此時(shí)還有其它進(jìn)程請(qǐng)求資源话速,則請(qǐng)求者只能等待讶踪,直至占有資源的進(jìn)程用畢釋放。
- 請(qǐng)求和保持條件:指進(jìn)程已經(jīng)保持至少一個(gè)資源泊交,但又提出了新的資源請(qǐng)求乳讥,而該資源已被其它進(jìn)程占有,此時(shí)請(qǐng)求進(jìn)程阻塞廓俭,但又對(duì)自己已獲得的其它資源保持不放云石。
- 不剝奪條件:指進(jìn)程已獲得的資源,在未使用完之前研乒,不能被剝奪汹忠,只能在使用完時(shí)由自己釋放。
- 環(huán)路等待條件:指在發(fā)生死鎖時(shí)告嘲,必然存在一個(gè)進(jìn)程——資源的環(huán)形鏈错维,即進(jìn)程集合{P0奖地,P1橄唬,P2,···参歹,Pn}中的P0正在等待一個(gè)P1占用的資源仰楚;P1正在等待P2占用的資源,……犬庇,Pn正在等待已被P0占用的資源僧界。
阻塞
由于資源短缺,而造成的部分程序暫停等待阻塞的原因
1臭挽、線程執(zhí)行了Thread.sleep(int millsecond);方法捂襟,當(dāng)前線程放棄CPU,睡眠一段時(shí)間欢峰,然后再恢復(fù)執(zhí)行
2葬荷、線程執(zhí)行一段同步代碼涨共,但是尚且無(wú)法獲得相關(guān)的同步鎖,只能進(jìn)入阻塞狀態(tài)宠漩,等到獲取了同步鎖举反,才能回復(fù)執(zhí)行
3、線程執(zhí)行某些IO操作扒吁,因?yàn)榈却嚓P(guān)的資源而進(jìn)入了阻塞狀態(tài)火鼻。比如說(shuō)監(jiān)聽(tīng)system.in,但是尚且沒(méi)有收到鍵盤(pán)的輸入雕崩,則進(jìn)入阻塞狀態(tài)魁索。
4、線程執(zhí)行了一個(gè)對(duì)象的wait()方法盼铁,直接進(jìn)入阻塞狀態(tài)蛾默,等待其他線程執(zhí)行notify()或者notifyAll()方法。
活鎖
活鎖指的是任務(wù)或者執(zhí)行者沒(méi)有被阻塞捉貌,由于某些條件沒(méi)有滿足支鸡,導(dǎo)致一直重復(fù)嘗試,失敗趁窃,嘗試牧挣,失敗。 活鎖和死鎖的區(qū)別在于醒陆,處于活鎖的實(shí)體是在不斷的改變狀態(tài)瀑构,所謂的“活”, 而處于死鎖的實(shí)體表現(xiàn)為等待刨摩;活鎖有可能自行解開(kāi)寺晌,死鎖則不能。
饑餓
這是個(gè)獨(dú)木橋(單進(jìn)程),橋上只能走一個(gè)人,B來(lái)到時(shí)A在橋上,B等待澡刹;而此時(shí)比B年齡小的C來(lái)了,B讓C現(xiàn)行(A走完后系統(tǒng)把進(jìn)程分給了C)呻征,C上橋后,D又來(lái)了,B又讓D現(xiàn)行(C走完后系統(tǒng)把進(jìn)程分個(gè)了D)以此類推B一直是等待狀態(tài).
原因
1、優(yōu)先級(jí)導(dǎo)致
2罢浇、同步鎖導(dǎo)致的陆赋,一個(gè)進(jìn)程的等待線程會(huì)有多個(gè),鎖釋放后嚷闭,隨機(jī)競(jìng)爭(zhēng)攒岛,和os調(diào)度有關(guān),這就會(huì)存在一種可能胞锰,某個(gè)線程運(yùn)氣極差灾锯,每次搶鎖都沒(méi)搶到。 而且新的線程還在不斷地進(jìn)入等鎖的隊(duì)列嗅榕,從而導(dǎo)致這個(gè)線程就幾乎是一直處于等待中顺饮。 這就使得這個(gè)“悲催”的線程就處于“饑餓”中色乾,而且還會(huì)悲慘的“餓死”。
3领突、我們知道notify()方法會(huì)喚醒對(duì)象條件隊(duì)列中等待的某個(gè)線程暖璧,但是,可惜這個(gè)喚醒是無(wú)序的(和VM調(diào)度君旦,OS調(diào)度有關(guān)澎办,甚至底層是隨機(jī)選取一個(gè),更甚至就是隊(duì)列中的第一個(gè))金砍。 而如果局蚀,條件隊(duì)列不斷有新的線程進(jìn)入,或者在喚醒的那一刻恕稠,剛好有其他線程搶入琅绅,那都可能導(dǎo)致某個(gè)運(yùn)氣不好的線程遲遲不能被喚醒。 對(duì)這個(gè)線程來(lái)說(shuō)鹅巍,就是進(jìn)入一種“饑餓”的狀態(tài)千扶,甚至還會(huì)有“餓死”的風(fēng)險(xiǎn)。
同步骆捧,異步澎羞,阻塞,非阻塞
1敛苇、同步: 多個(gè)任務(wù)之間有先后順序執(zhí)行妆绞,一個(gè)執(zhí)行完下個(gè)才能執(zhí)行
2、異步: 多個(gè)任務(wù)之間沒(méi)有先后順序枫攀,可以同時(shí)執(zhí)行括饶,有時(shí)候一個(gè)任務(wù)可能要在必要的時(shí)候獲取另一個(gè)同時(shí)執(zhí)行的任務(wù)的結(jié)果,這個(gè)就叫回調(diào)来涨!
3图焰、阻塞: 如果卡住了調(diào)用者,調(diào)用者不能繼續(xù)往下執(zhí)行扫夜,就是說(shuō)調(diào)用者阻塞了
4楞泼、非阻塞: 如果不會(huì)卡住驰徊,可以繼續(xù)執(zhí)行笤闯,就是說(shuō)非阻塞的
同步異步相對(duì)于多任務(wù)而言,阻塞非阻塞相對(duì)于代碼執(zhí)行而言棍厂。
python的多進(jìn)程和多線程對(duì)比
程序?yàn)榇鎯?chǔ)在磁盤(pán)上的可執(zhí)行文件颗味,當(dāng)把程序加載到內(nèi)存中并被操作系統(tǒng)調(diào)用,則擁有了生命周期牺弹,進(jìn)程即為運(yùn)行中的程序浦马。
一個(gè)進(jìn)程可以并行(類似于異步)運(yùn)行多個(gè)線程时呀,每個(gè)線程執(zhí)行不同的任務(wù),也就是說(shuō)線程是進(jìn)程的組成部分晶默。
當(dāng)一個(gè)進(jìn)程啟動(dòng)時(shí)至少要執(zhí)行一個(gè)任務(wù)谨娜,因此至少有一個(gè)主線程,由主線程再創(chuàng)建其他的子線程磺陡。
多線程的執(zhí)行方式和多進(jìn)程相似趴梢,由操作系統(tǒng)在多個(gè)線程之間快速切換,讓每個(gè)線程都短暫的交替運(yùn)行币他,看起來(lái)像同時(shí)執(zhí)行一樣坞靶。當(dāng)然,多核CPU可真正意義上實(shí)現(xiàn)多線程或多進(jìn)程的同時(shí)執(zhí)行蝴悉。
進(jìn)程和線程之間存在不同的特點(diǎn)彰阴。
每個(gè)進(jìn)程擁有自己的地址空間、內(nèi)存和數(shù)據(jù)棧拍冠,由操作系統(tǒng)管理所有的進(jìn)程尿这,并為其合理分配執(zhí)行時(shí)間。
由于進(jìn)程間資源相互獨(dú)立庆杜,不同進(jìn)程之間需要通過(guò)IPC(進(jìn)程間通信)
方式共享信息妻味,但單個(gè)進(jìn)程崩潰時(shí)不會(huì)導(dǎo)致系統(tǒng)崩潰。
而多線程是在同一個(gè)進(jìn)程下執(zhí)行的欣福,共享同一片數(shù)據(jù)空間责球,相比于進(jìn)程而言,線程間的信息共享更加容易拓劝,但當(dāng)一個(gè)線程崩潰時(shí)會(huì)導(dǎo)致整個(gè)進(jìn)程崩潰
補(bǔ)充: 并發(fā)與并行:
并發(fā): 不會(huì)在同一時(shí)刻同時(shí)運(yùn)行雏逾,存在交替執(zhí)行的情況,交替做不同事的能力
并行: 同一時(shí)刻多個(gè)任務(wù)同時(shí)運(yùn)行郑临,同時(shí)做不同事的能力
程序需要執(zhí)行較多的讀寫(xiě)栖博、請(qǐng)求和回復(fù)任務(wù)的需要大量的IO操作,IO密集型操作使用并發(fā)更好厢洞。
CPU運(yùn)算量大的程序仇让,使用并行會(huì)更好
python中進(jìn)程與線程的使用場(chǎng)景?
多進(jìn)程適合在CPU密集操作(cpu操作指令比較多躺翻,如位多的的浮點(diǎn)運(yùn)算)丧叽。
多線程適合在IO密性型操作(讀寫(xiě)數(shù)據(jù)操作比多的的,比如爬蟲(chóng))
GIL鏈接