多線程基本介紹
有很多場景中的事是同時進行的,比如開車的時候手和腳共同來駕駛汽車,再比如唱歌跳舞同時進行
如何創(chuàng)建線程
· 方法一:通過函數(shù)
? ?使用 threading 模塊中的Thread類, 在這個類中有一個target參數(shù)需要傳遞一個函數(shù)對象。而這個函數(shù)內(nèi),就是多線程的邏輯

?· 方法二:通過類的方式
? ? 創(chuàng)建一個類,當時這個類需要基礎(chǔ)threading.Thread。并實現(xiàn)(重寫) run()方法。在 run() 方法中實現(xiàn)多線程的邏輯

主線程和子線程的執(zhí)行優(yōu)先級
· 主線程會等待子線程結(jié)束之后再結(jié)束

· join(),等待子線程全部結(jié)束后,主線程序才繼續(xù)執(zhí)行

· setDaemon() 守護線程,不會等待子線程結(jié)束,主線程先行結(jié)束

程序中模擬多任務(wù)

驗證子線程的執(zhí)行與創(chuàng)建
當調(diào)用Thread的時候,不會去創(chuàng)建線程
當調(diào)用Thread創(chuàng)建出來的實例對象的start方法的時候,才會創(chuàng)建線程以及開始運行這個線程

enumerate()用來查看當前活動線程的數(shù)量

線程間共享全局變量
在一個函數(shù)中,對全局變量進行修改的時候,是否要加global要看是否對全局變量的指向進行了修改,如果修改了指向,那么必須使用global,僅僅是修改了指向的空間中的數(shù)據(jù),此時不用必須使用global, 線程是共享全局變量的

線程間的資源競爭
一個線程寫入,一個線程讀取,如果兩個線程都寫入呢?
互斥鎖和死鎖
· 互斥鎖
當多個線程幾乎同時修改一個共享數(shù)據(jù)的時候,需要進行同步控制
某個線程要更改共享數(shù)據(jù)時,先將其鎖定,此時資源的狀態(tài)為“鎖定”,其它線程不能改變。
只到該線程釋放資源,將資源的狀態(tài)變成“非鎖定”,其它的線程才能再次鎖定該資源。
互斥鎖保證了每次只有一個線程進行寫入操作,從而保證了多線程情況下數(shù)據(jù)的正確性。
創(chuàng)建鎖
mutex = threading.Lock()
鎖定
mutex. acquire()
解鎖
mutex.release()
? · 死 鎖
? ? 在線程間共享多個資源的時候,如果兩個線程分別占有一部分資源并且同時等待對方的資源,就會造成死鎖
· 通過Threading.Lock()創(chuàng)建的鎖是不可重復(fù)的鎖
? 也就是mutex.acquire()? 與mutex.release()是成對出現(xiàn)的。
? 不能出現(xiàn)?mutex.acquire() 后又重復(fù)跟了一個?mutex.acquire()


· 避免死鎖
? · 程序設(shè)計時要盡量避免
? · 添加超時時間
Queue 線程
在線程中,訪問一些全局變量,加鎖是一個經(jīng)常的過程。如果是想把一些數(shù)據(jù)存儲到某個隊列中,那么python內(nèi)置了一個線程安全的模塊叫做queue模塊。
python 中的queue模塊中提供了同步的、線程安全的隊列類,包括FIFO(進先出)隊列)隊列Queue,
LIFO( 先入后出 )隊列LifoQueue
這些隊列都實現(xiàn)?了鎖原語(可以理解為原子操作,要么不做,要么都做完),能夠在多線程中直接使用??梢允褂藐犃衼韺崿F(xiàn)線程間的異步

生產(chǎn)者和消費者
生產(chǎn)者和消費者模式是多線程開發(fā)中常見的一種模式。通過生產(chǎn)者和消費者模式,可以讓代碼達到高內(nèi)聚低耦合的目標,線程管理更加方便,程序分工更加明確。
生產(chǎn)者的線程專門用來生產(chǎn)一些數(shù)據(jù),然后存放到容器中(中間變量)。消費者在從這個中間的容器中取出數(shù)據(jù)進行消費

Lock版生產(chǎn)者與消費者示例:


Condition版的生產(chǎn)者和消費者示例:

