這就是一個(gè)線程的基本使用方式,定義一個(gè)run方法 使用的時(shí)候創(chuàng)建線程對(duì)象,然后線程對(duì)象.start(),就表示開啟這個(gè)線程,執(zhí)行run方法 線程對(duì)象的創(chuàng)建方式是threading.Thread(target=run,ages=(參數(shù)1,參數(shù)2,))如果只是一個(gè)參數(shù)那這個(gè)參數(shù)也要有逗號(hào) 除了上面的方法來創(chuàng)建線程,還有使用類的方式來創(chuàng)建一個(gè)線程 創(chuàng)建一個(gè)類,然后實(shí)現(xiàn)Thread類,那么這個(gè)類就是線程類 運(yùn)行的線程的時(shí)候,首先是創(chuàng)建一個(gè)線程對(duì)象,然后調(diào)用start方法來運(yùn)行運(yùn)行run方法 案例,計(jì)算50個(gè)線程的運(yùn)行時(shí)間這個(gè)程序的思想是:開啟50個(gè)線程,每個(gè)線程睡眠兩秒鐘,計(jì)算這50個(gè)線程的運(yùn)行時(shí)間,如果不是多線程,那么每個(gè)兩秒,50個(gè)那就是100秒,但是多線程讓這50個(gè)只用2秒多一點(diǎn) 這個(gè)程序的關(guān)鍵是: 如何才能再50個(gè)線程執(zhí)行完畢之后,才執(zhí)行最后一句代碼,計(jì)算出所有線程的執(zhí)行時(shí)間 這就要保證50個(gè)線程只要不結(jié)束就不執(zhí)行這一句 可以使用線程對(duì)象.join()方法,這個(gè)方法的意思是當(dāng)前線程對(duì)象的run方法結(jié)束程序才往下走 比如t1.join()方法的意思是程序堵塞在這,什么時(shí)候t1線程執(zhí)行完畢什么時(shí)候程序往下走 這個(gè)程序的的關(guān)鍵在于,只要?jiǎng)?chuàng)建一個(gè)線程就放入一個(gè)列表,然后遍歷所有列表中的線程對(duì)象,每一個(gè)都join,也就是等待每一個(gè)線程都執(zhí)行完畢,程序才往下執(zhí)行,最終輸出執(zhí)行的時(shí)間 守護(hù)線程 以上代碼就是設(shè)置當(dāng)前線程為守護(hù)線程,守護(hù)是為主線程守護(hù),只要主線程執(zhí)行完畢,這些線程就不執(zhí)行了 線程鎖當(dāng)多個(gè)線程共同操作同一個(gè)變量的時(shí)候,加鎖可以保證數(shù)據(jù)的安全 在主線程中threading.lock()這個(gè)方法的意思是創(chuàng)建一個(gè)鎖對(duì)象 lock.acquire()的意思是開啟這個(gè)鎖,哪個(gè)線程拿到這個(gè)鎖之后,其它線程就拿不到了,只有等這個(gè)線程釋放之后(lock.release()),才可以拿到這個(gè)鎖進(jìn)而執(zhí)行這個(gè)鎖后面的內(nèi)容。 遞歸鎖 threading.Lock()加載線程的鎖對(duì)象,是一個(gè)基本的鎖對(duì)象,一次只能一個(gè)鎖定,其余鎖請(qǐng)求,需等待鎖釋放后才能獲取,也就是說下面的程序會(huì)出問題 這個(gè)程序會(huì)出問題,原因就是threadking.Lock()只能鎖一次,就是說一個(gè)線程中只能被一次acquire,其余的鎖請(qǐng)求只能在這一次釋放之后才可以 分析程序t.start之后會(huì)開啟run3線程此時(shí)鎖定,run3內(nèi)部調(diào)用run1(并沒有開啟線程),run1內(nèi)部也想要鎖,但是run3鎖的那次還沒有釋放呢,所以他獲取不到鎖,該t線程就會(huì)堵塞在這里,所以下面的while循環(huán)就會(huì)一直執(zhí)行,因?yàn)闀?huì)一共有兩個(gè)線程(包含主線程)會(huì)一直運(yùn)行,永遠(yuǎn)不等于1,所以while不停止 解決這種情況需要:使用RLock()鎖 threading.RLock() 多重鎖,在同一線程中可用被多次acquire。如果使用RLock,那么acquire和release必須成對(duì)出現(xiàn), 調(diào)用了n次acquire鎖請(qǐng)求,則必須調(diào)用n次的release才能在線程中釋放鎖對(duì)象 既然可以鎖多次,那么上面的程序在執(zhí)行run1方法的時(shí)候,也可以獲取到鎖,所以程序不會(huì)堵塞,也會(huì)往下繼續(xù)運(yùn)行。 線程之信號(hào)量: 線程鎖又叫互斥鎖同時(shí)只允許一個(gè)線程修改數(shù)據(jù),也就是一個(gè)線程獲取到這個(gè)鎖之后,其它的線程是獲取不到這個(gè)鎖的,只能等待,等待這個(gè)線程釋放鎖之后,哪個(gè)線程得到鎖之后就可以繼續(xù)執(zhí)行,沒有得到鎖的線程將繼續(xù)等待。 而Semaphore同時(shí)允許指定數(shù)量的線程獲取這個(gè)鎖,也就是說這個(gè)鎖可以同時(shí)被多個(gè)線程所共用,比如設(shè)置可以3個(gè)共用鎖,則3個(gè)線程可以一起運(yùn)行鎖之后的內(nèi)部,釋放一個(gè)就會(huì)有一個(gè)線程可以獲取到鎖。 如上面的程序,threading.BuondedSemaphore(5)的意思就是設(shè)置最多允許5個(gè)線程同時(shí)運(yùn)行 線程之event: Event(事件):事件處理的機(jī)制:全局定義了一個(gè)內(nèi)置標(biāo)志Flag,就是內(nèi)部核心是flag,如果Flag值為False,那么當(dāng)程序執(zhí)行event.wait方法時(shí)就會(huì)阻塞,如果Flag值為True,那么event.wait 方法時(shí)便不再阻塞。 Event沒有鎖,無法使線程進(jìn)入同步阻塞狀態(tài)。 Event()的方法
這個(gè)程序有兩個(gè)線程,一個(gè)車線程一個(gè)紅綠燈線程,車要根據(jù)紅綠燈的情況進(jìn)行行動(dòng),紅綠燈會(huì)自動(dòng)按照時(shí)間來來回回的變化,而車要根據(jù)紅綠燈來來回回的變化,再兩個(gè)線程傳遞信息的橋梁就是event 紅綠燈規(guī)則是這樣的,當(dāng)count只要小于5就表示綠燈,event。set將標(biāo)志位設(shè)置為true 5到10設(shè)置為紅燈,event.clear將標(biāo)志位設(shè)置為false 大于10,則count為0,并且社會(huì)綠燈event。set 這里面的所有情況都可以根據(jù)event來獲取,所以車只要根據(jù)event就可以判斷當(dāng)前紅綠燈的情況 車的判斷: 只要event.isset就表示當(dāng)前為綠燈,可以執(zhí)行,如果不是則表示綠燈,此時(shí)應(yīng)該等待,執(zhí)行wait,此時(shí)堵塞,什么時(shí)候標(biāo)志位為true,也就是綠燈的時(shí)候wait就不堵塞了,就可以往下運(yùn)行了 |
|