微吼云上線多路互動(dòng)直播服務(wù) 加速多場(chǎng)景互動(dòng)直播落地
758
2025-03-31
項(xiàng)目中多線程的目的
具體原理我覺得這應(yīng)該是可以跳到操作系統(tǒng)里面了一點(diǎn)點(diǎn)小小總結(jié)大家還可以找本操作系統(tǒng)的書看看,老規(guī)矩找不到的話找我主頁(yè),有一個(gè)關(guān)于資源的文章里面有資源當(dāng)然也可以私信我。
我們?cè)僬f說我們項(xiàng)目里面用多線程的目的:
1.線程之間共享內(nèi)存非常容易。
2·使用多線程來實(shí)現(xiàn)多任務(wù)并發(fā)執(zhí)行比使用多進(jìn)程的效率高
3·有時(shí)候可以節(jié)省運(yùn)行時(shí)間,這個(gè)一會(huì)在下面就會(huì)知道
4·當(dāng)你一個(gè)文件要同時(shí)執(zhí)行多個(gè)功能時(shí)就可以用到多線程
python語(yǔ)言內(nèi)置了多線程功能支持,而不是單純地作為底層操作系統(tǒng)的調(diào)度方式,從而簡(jiǎn)化了python的多線程編程。
實(shí)戰(zhàn)操作
說這么多不如實(shí)際動(dòng)手練練,首先導(dǎo)入線程
特別注意:
大家在見建文件的時(shí)候名字千萬(wàn)別和導(dǎo)入的包threading一樣不然會(huì)出錯(cuò)的。
小知識(shí)
import threading
讓我們先看看自己程序現(xiàn)在有多少個(gè)進(jìn)程
import threading def main(): print(threading.current_thread()) if __name__ == '__main__': main()
結(jié)果:1#我的就一個(gè)你的呢?
如果你的進(jìn)程不為一的話還可以這樣查看每一個(gè)進(jìn)程名
import threading def main(): print(threading.active_count()) print(threading.enumerate()) if __name__ == '__main__': main()
>>>[<_MainThread(MainThread, started 36004)>]#返回的是一個(gè)列表因?yàn)槲业哪壳熬鸵粋€(gè)所以就一個(gè)主進(jìn)程
還可以查看正在運(yùn)行的進(jìn)程
import threading def main(): print(threading.active_count()) print(threading.enumerate()) print(threading.current_thread()) if __name__ == '__main__': main()
>1 [<_MainThread(MainThread, started 36004)>] <_MainThread(MainThread, started 36004)>
創(chuàng)建一個(gè)簡(jiǎn)單的線程
首先我們先介紹一下threading.Thread()里面的參數(shù),大家學(xué)python每個(gè)模塊的功能時(shí)最好還是看一下源文件內(nèi)容,這樣有助于提高你的編程能力:
需要注意的點(diǎn)我已經(jīng)打上標(biāo)記了
import threading def first(): print("frist active") print("frist finish") def main(): first_thread=threading.Thread(target=first,name="T1") first_thread.start()#開始的標(biāo)志 print("main") if __name__ == '__main__': main()
結(jié)果: 第一次運(yùn)行 frist active main frist finish 第二次運(yùn)行 frist active frist finish main
每次的結(jié)果不一樣就已經(jīng)表明Frist和main是同時(shí)運(yùn)行的了。
如果說效果不太明顯的話,我們改進(jìn)一下接下來我們引入
import time
import threading import time def first(): print("frist active") time.sleep(3) print("frist finish") def main(): first_thread=threading.Thread(target=first,name="T1") first_thread.start() print("main") if __name__ == '__main__': main()
結(jié)果: frist active main frist finish
因?yàn)閳?zhí)行到Frist active的時(shí)候Frist線程要睡3秒這個(gè)時(shí)候main還在執(zhí)行所以這樣每次都是這個(gè)結(jié)果了。
特別強(qiáng)調(diào)target=first不是導(dǎo)入Frist函數(shù)從源文件我們就已經(jīng)看出是通過run()方法進(jìn)行的,這里解釋我引用一位大佬解釋
當(dāng)然如果你覺得這樣不行的話你也可以重寫threading.Thresd里的run方法來個(gè)自定義線程
class MyThread(threading.Thread): def __init__(self,n): super(MyThread,self).__init__() #重構(gòu)run函數(shù)必須寫 self.n = n def run(self): print('task',self.n) time.sleep(1) print('2s') time.sleep(1) print('1s') time.sleep(1) print('0s') time.sleep(1) if __name__ == '__main__': t1 = MyThread('t1') t2 = MyThread('t2') t1.start() t2.start()
結(jié)果: task t1 task t2 2s 2s 1s 1s 0s 0s
守護(hù)線程
所謂’線程守護(hù)’,就是主線程不管該線程的執(zhí)行情況,只要是其他子線程結(jié)束且主線程執(zhí)行完畢,主線程都會(huì)關(guān)閉。也就是說:主線程不等待該守護(hù)線程的執(zhí)行完再去關(guān)閉。
不好理解的話來看看例子
import threading import time def first(): print("frist active") time.sleep(3) print("frist finish") def second(): print("second active") print("second finish") def main(): first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.setDaemon(True)#一定要在start()前開始 first_thread.start() second_thresd.start() print("main") if __name__ == '__main__': main()
結(jié)果 frist active second active second finishjiemeijieshu main
當(dāng)主線程和其他子線程都結(jié)束不管守護(hù)線程first_thread 結(jié)沒結(jié)束程序都結(jié)束
當(dāng)設(shè)second_thresd為守護(hù)線程的時(shí)候情況是這樣的
import threading import time def first(): print("frist active") time.sleep(3) print("frist finish") def second(): print("second active") print("second finish") def main(): first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") second_thresd.setDaemon(True)#一定要在start()前開始 first_thread.start() second_thresd.start() print("main") if __name__ == '__main__': main()
frist active second active second finish main frist finish #盡管輸出這個(gè)要等三秒
主進(jìn)程等待子進(jìn)程結(jié)束
為了讓守護(hù)線程執(zhí)行結(jié)束之后,主線程再結(jié)束,我們可以使用join方法,讓主線程等待子線程執(zhí)行
import threading import time def first(): print("frist active") time.sleep(3) print("frist finish") def second(): print("second active") print("second finish") def main(): first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.start() second_thresd.start() first_thread.join() print("main") if __name__ == '__main__': main()
結(jié)果: frist active second active second finish frist finish main 不加join是這樣的結(jié)果 frist active second active second finish main frist finish
共享全局變量的特性
這里定義一個(gè)全局變量A
import threading import time def first(): global A print("frist active") time.sleep(3) A=A+3 print("frist:%d"%A) print("frist finish") def second(): global A print("second active") A=A+6 print("second:%d"%A) print("second finish") def main(): global A first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.start() second_thresd.start() #first_thread.join() print("main") A=A+3 print("mian:%d"%A) if __name__ == '__main__': A=0 main()
來看一下結(jié)果
frist active second active second:6 second finish main mian:9 frist:12 frist finish
鎖
由上面的例子可以看出,輸出A的值的時(shí)候不同進(jìn)程之間的資源是共享的這就導(dǎo)致了變量A的值不固定造成了臟數(shù)據(jù)的情況,不理解的話我們就來個(gè)例子。
在沒有互斥鎖的情況下,假設(shè)賬戶有一萬(wàn)元錢,存錢和取錢同時(shí)進(jìn)行可能賬戶余額會(huì)有一萬(wàn)一千元。這樣我當(dāng)然高興只是銀行不答應(yīng)。為了避免這種情況我們引入鎖的概念,下面我們簡(jiǎn)單的介紹幾種編程里面常用的。
互斥鎖
import threading import time def first(): global A,lock lock.acquire() print("frist active") time.sleep(3) A=A+3 print("frist:%d"%A) print("frist finish") lock.release() def second(): global A,lock lock.acquire() print("second active") A=A+6 print("second:%d"%A) print("second finish") lock.release def main(): global A,lock lock=threading.Lock() first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.start() second_thresd.start() #first_thread.join() print("main") A=A+3 print("mian:%d"%A) if __name__ == '__main__': A=0 main()
結(jié)果
frist active main mian:3 frist:6 frist finish second active second:12 second finish
是不是這樣看著就舒服多了,如果例子不夠明顯我們?cè)賮硪粋€(gè)
import threading import time def first(): global A,lock lock.acquire() print("frist active") time.sleep(3) A=A+3 print("frist1:%d"%A) A = A + 3 print("frist2:%d" % A) print("frist finish") lock.release() def second(): global A,lock lock.acquire() print("second active") A=A+6 print("second1:%d"%A) A=A+6 print("second2:%d"%A) print("second finish") lock.release() def main(): global A,lock lock=threading.Lock() first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.start() second_thresd.start() #first_thread.join() print("main") A=A+3 print("mian:%d"%A) if __name__ == '__main__': A=0 main()
結(jié)果
frist active main mian:3 frist1:6 frist2:9 frist finish second active second1:15 second2:21 second finish 去掉鎖以后結(jié)果 frist active second active second1:6 second2:12 second finish main mian:15 frist1:18 frist2:21 frist finish
很明顯去掉鎖以后結(jié)果雜亂的很
信號(hào)量
我相信對(duì)操作系統(tǒng)有一定了解的肯定,在剛才提到鎖的時(shí)候就想到了信號(hào)量畢竟考研題經(jīng)常會(huì)出現(xiàn),同步,互斥和信號(hào)量機(jī)制。我們就來說一說信號(hào)量鎖,其實(shí)道理很簡(jiǎn)單假如你現(xiàn)在,在中國(guó)結(jié)婚了你只能娶一個(gè)老婆吧,盡管你可以去找別的女人但他們不能稱為老婆她們會(huì)被稱為小三,二奶啊等等,這里老婆這個(gè)信號(hào)量在中國(guó)就是==一==只能有一個(gè),別的再來就不可以了。
import threading import time def run(n,semaphore): semaphore.acquire() #加鎖 time.sleep(3) print('run the thread:%s\n' % n) semaphore.release() #釋放 if __name__== '__main__': num=0 semaphore = threading.BoundedSemaphore(3) #最多允許3個(gè)線程同時(shí)運(yùn)行 for i in range(10): t = threading.Thread(target=run,args=('t-%s' % i,semaphore)) t.start() while threading.active_count() !=1: pass else: print('----------all threads done-----------')
結(jié)果
run the thread:t-2 run the thread:t-1 run the thread:t-0 run the thread:t-3 run the thread:t-5 run the thread:t-4 run the thread:t-6 run the thread:t-7 run the thread:t-8 run the thread:t-9 ----------all threads done-----------
任務(wù)調(diào)度 多線程
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。