多線程-threading
python的thread模塊是比較底層的模塊,python的threading模塊是對(duì)thread做了一些包裝的,可以更加方便的被使用


1.可以明顯看出使用了多線程并發(fā)的操作,花費(fèi)時(shí)間要短很多
2.創(chuàng)建好的線程,需要調(diào)用start()方法來啟動(dòng)
線程的執(zhí)行順序

結(jié)果來看:主線程會(huì)等待所有的子線程結(jié)束后才結(jié)束

從代碼和執(zhí)行結(jié)果我們可以看出,多線程程序的執(zhí)行順序是不確定的。當(dāng)執(zhí)行到sleep語句時(shí),線程將被阻塞(Blocked),到sleep結(jié)束后,線程進(jìn)入就緒(Runnable)狀態(tài),等待調(diào)度。而線程調(diào)度將自行選擇一個(gè)線程執(zhí)行。上面的代碼中只能保證每個(gè)線程都運(yùn)行完整個(gè)run函數(shù),但是線程的啟動(dòng)順序、run函數(shù)中每次循環(huán)的執(zhí)行順序都不能確定。
查看線程數(shù)量

線程中的守護(hù)進(jìn)程

線程執(zhí)行代碼的封裝
通過使用threading模塊能完成多任務(wù)的程序開發(fā),為了讓每個(gè)線程的封裝性更完美,所以使用threading模塊時(shí),往往會(huì)定義一個(gè)新的子類class,只要繼承threading.Thread就可以了,然后重寫run方法

說明
·python的threading.Thread類有一個(gè)run方法,用于定義線程的功能函數(shù),可以在自己的線程類中覆蓋該方法。而創(chuàng)建自己的線程實(shí)例后,通過Thread類的start方法,可以啟動(dòng)該線程,交給python虛擬機(jī)進(jìn)行調(diào)度,當(dāng)該線程獲得執(zhí)行的機(jī)會(huì)時(shí),就會(huì)調(diào)用run方法執(zhí)行線程。
多線程-共享全局變量


總結(jié):
·在一個(gè)進(jìn)程內(nèi)的所有線程共享全局變量,能夠在不適用其他方式的前提下完成多線程之間的數(shù)據(jù)共享(這點(diǎn)要比多進(jìn)程要好)
·缺點(diǎn)就是,線程是對(duì)全局變量隨意遂改可能造成多線程之間對(duì)全局變量的混亂(即線程非安全)
進(jìn)程VS線程
·進(jìn)程,能夠完成多任務(wù),比如?在一臺(tái)電腦上能夠同時(shí)運(yùn)行多個(gè)QQ
·線程,能夠完成多任務(wù),比如?一個(gè)QQ中的多個(gè)聊天窗口
定義的不同
·進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位.
·線程是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),但是它可與同屬一個(gè)進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源.
區(qū)別
·一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程.
·線程的劃分尺度小于進(jìn)程(資源比進(jìn)程少),使得多線程程序的并發(fā)性高。
·進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存,從而極大地提高了程序的運(yùn)行效率
·線程不能夠獨(dú)立執(zhí)行,必須依存在進(jìn)程中
優(yōu)缺點(diǎn)
線程和進(jìn)程在使用上各有優(yōu)缺點(diǎn):線程執(zhí)行開銷小,但不利于資源的管理和保護(hù);而進(jìn)程正相反。
同步的概念
1.多線程開發(fā)可能遇到的問題
同步不是一起的意思,是協(xié)同步調(diào)

2.什么是同步
同步就是協(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ù)操作。
3.解決問題的思路
對(duì)于本小節(jié)提出的那個(gè)計(jì)算錯(cuò)誤的問題,可以通過線程同步來進(jìn)行解決
思路,如下:
1.系統(tǒng)調(diào)用t1,然后獲取到num的值為0,此時(shí)上一把鎖,即不允許其他現(xiàn)在操作num
2.對(duì)num的值進(jìn)行+1
3.解鎖,此時(shí)num的值為1,其他的線程就可以使用num了,而且是num的值不是0而是1
4.同理其他線程在對(duì)num進(jìn)行修改時(shí),都要先上鎖,處理完后再解鎖,在上鎖的整個(gè)過程中不允許其他線程訪問,就保證了數(shù)據(jù)的正確性
互斥鎖
當(dāng)多個(gè)線程幾乎同時(shí)修改某一個(gè)共享數(shù)據(jù)的時(shí)候,需要進(jìn)行同步控制
線程同步能夠保證多個(gè)線程安全訪問競(jìng)爭(zhēng)資源,最簡(jiǎn)單的同步機(jī)制是引入互斥鎖。
互斥鎖為資源引入一個(gè)狀態(tài):鎖定/非鎖定。
某個(gè)線程要更改共享數(shù)據(jù)時(shí),先將其鎖定,此時(shí)資源的狀態(tài)為“鎖定”,其他線程不能更改;直到該線程釋放資源,將資源的狀態(tài)變成“非鎖定”,其他的線程才能再次鎖定該資源?;コ怄i保證了每次只有一個(gè)線程進(jìn)行寫入操作,從而保證了多線程情況下數(shù)據(jù)的正確性。
引出鎖

鎖的實(shí)例1:

上鎖解鎖過程
當(dāng)一個(gè)線程調(diào)用鎖的acquire()方法獲得鎖時(shí),鎖就進(jìn)入“l(fā)ocked”狀態(tài)。
每次只有一個(gè)線程可以獲得鎖。如果此時(shí)另一個(gè)線程試圖獲得這個(gè)鎖,該線程就會(huì)變?yōu)椤癰locked”狀態(tài),稱為“阻塞”,直到擁有鎖的線程調(diào)用鎖的release()方法釋放鎖之后,鎖進(jìn)入“unlocked”狀態(tài)。
線程調(diào)度程序從處于同步阻塞狀態(tài)的線程中選擇一個(gè)來獲得鎖,并使得該線程進(jìn)入運(yùn)行(running)狀態(tài)。
總結(jié)
鎖的好處:
·確保了某段關(guān)鍵代碼只能由一個(gè)線程從頭到尾完整地執(zhí)行
鎖的壞處:
·阻止了多線程并發(fā)執(zhí)行,包含鎖的某段代碼實(shí)際上只能以單線程模式執(zhí)行,效率就大大地下降了
·由于可以存在多個(gè)鎖,不同的線程持有不同的鎖,并試圖獲取對(duì)方持有的鎖時(shí),可能會(huì)造成死鎖
多線程-非共享數(shù)
對(duì)于全局變量,在多線程中要格外小心,否則容易造成數(shù)據(jù)錯(cuò)亂的情況發(fā)生
1.非全局變量是否要加鎖呢?

結(jié)論:·在多線程開發(fā)中,全局變量是多個(gè)線程都共享的數(shù)據(jù),而局部變量等是各自線程的,是非共享的
死鎖
在線程間共享多個(gè)資源的時(shí)候,如果兩個(gè)線程分別占有一部分資源并且同時(shí)等待對(duì)方的資源,就會(huì)造成死鎖。
盡管死鎖很少發(fā)生,但一旦發(fā)生就會(huì)造成應(yīng)用的停止響應(yīng)

同步應(yīng)用
多個(gè)線程有序執(zhí)行
·可以使用互斥鎖完成多個(gè)任務(wù),有序的進(jìn)程工作,這就是線程的同步

生產(chǎn)者與消費(fèi)者模式
3.?Queue的說明
1.對(duì)于Queue,在多線程通信之間扮演重要的角色
2.添加數(shù)據(jù)到隊(duì)列中,使用put()方法
3.從隊(duì)列中取數(shù)據(jù),使用get()方法
4.判斷隊(duì)列中是否還有數(shù)據(jù),使用qsize()方法
4.生產(chǎn)者消費(fèi)者模式的說明
·為什么要使用生產(chǎn)者和消費(fèi)者模式
在線程世界里,生產(chǎn)者就是生產(chǎn)數(shù)據(jù)的線程,消費(fèi)者就是消費(fèi)數(shù)據(jù)的線程。在多線程開發(fā)當(dāng)中,如果生產(chǎn)者處理速度很快,而消費(fèi)者處理速度很慢,那么生產(chǎn)者就必須等待消費(fèi)者處理完,才能繼續(xù)生產(chǎn)數(shù)據(jù)。同樣的道理,如果消費(fèi)者的處理能力大于生產(chǎn)者,那么消費(fèi)者就必須等待生產(chǎn)者。為了解決這個(gè)問題于是引入了生產(chǎn)者和消費(fèi)者模式。
·什么是生產(chǎn)者消費(fèi)者模式
生產(chǎn)者消費(fèi)者模式是通過一個(gè)容器來解決生產(chǎn)者和消費(fèi)者的強(qiáng)耦合問題。生產(chǎn)者和消費(fèi)者彼此之間不直接通訊,而通過阻塞隊(duì)列來進(jìn)行通訊,所以生產(chǎn)者生產(chǎn)完數(shù)據(jù)之后不用等待消費(fèi)者處理,直接扔給阻塞隊(duì)列,消費(fèi)者不找生產(chǎn)者要數(shù)據(jù),而是直接從阻塞隊(duì)列里取,阻塞隊(duì)列就相當(dāng)于一個(gè)緩沖區(qū),平衡了生產(chǎn)者和消費(fèi)者的處理能力。
這個(gè)阻塞隊(duì)列就是用來給生產(chǎn)者和消費(fèi)者解耦的??v觀大多數(shù)設(shè)計(jì)模式,都會(huì)找一個(gè)第三者出來進(jìn)行解耦,
