python 線程 ~~ ~~~為面試開辟VIP通道~~~~~測(cè)試、死鎖、全局變量共享、守護(hù)主線程等。。。。。。

      網(wǎng)友投稿 895 2025-03-31

      線程(英語(yǔ):thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。線程很重要,通過本篇文章可以讓你們很好的了解線程的傳參、線程執(zhí)行規(guī)則、守護(hù)主線程、線程間共享全局變量、進(jìn)程互斥鎖、死鎖進(jìn)程怎么解決。希望對(duì)你們有所幫助。


      在了解線程之間的操作及進(jìn)程死鎖之前先來了解一下什么是進(jìn)程?以下是官方的解釋。

      線程(英語(yǔ):thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。一條線程指的是進(jìn)程中一個(gè)單一順序的控制流,一個(gè)進(jìn)程中可以并發(fā)多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù)。在Unix System V及SunOS中也被稱為輕量進(jìn)程(lightweight processes),但輕量進(jìn)程更多指內(nèi)核線程(kernel thread),而把用戶線程(user thread)稱為線程。

      線程是獨(dú)立調(diào)度和分派的基本單位。線程可以為操作系統(tǒng)內(nèi)核調(diào)度的內(nèi)核線程,如Win32線程;由用戶進(jìn)程自行調(diào)度的用戶線程,如Linux平臺(tái)的POSIX Thread;或者由內(nèi)核與用戶進(jìn)程,如Windows 7的線程,進(jìn)行混合調(diào)度。

      同一進(jìn)程中的多條線程將共享該進(jìn)程中的全部系統(tǒng)資源,如虛擬地址空間,文件描述符和信號(hào)處理等等。但同一進(jìn)程中的多個(gè)線程有各自的調(diào)用棧(call stack),自己的寄存器環(huán)境(register context),自己的線程本地存儲(chǔ)(thread-local storage)。

      一個(gè)進(jìn)程可以有很多線程,每條線程并行執(zhí)行不同的任務(wù)。

      在多核或多CPU,或支持Hyper-threading的CPU上使用多線程程序設(shè)計(jì)的好處是顯而易見,即提高了程序的執(zhí)行吞吐率。在單CPU單核的計(jì)算機(jī)上,使用多線程技術(shù),也可以把進(jìn)程中負(fù)責(zé)I/O處理、人機(jī)交互而常被阻塞的部分與密集計(jì)算的部分分開來執(zhí)行,編寫專門的workhorse線程執(zhí)行密集計(jì)算,從而提高了程序的執(zhí)行效率。

      看著是不是非常的暈,沒關(guān)系,下面讓我們用實(shí)例來享受線程帶來的舒適。

      **

      1、線程之元組傳參

      **

      沒錯(cuò),你沒有看錯(cuò),和前面所說的進(jìn)程一樣,線程也可以用元組傳參。這樣說吧,只要有函數(shù)的存在基本上都能以元組傳參。下面來看一下元組是怎么傳參的

      # TODO 鳥欲高飛,必先展翅 # TODO 向前的人 :Jhon # TODO 元組 import threading import time def task(count): for i in range(count): print("正在工作") time.sleep(0.2) else: print("工作結(jié)束") if __name__ == '__main__': #創(chuàng)建子線條程 task_thred=threading.Thread(target=task,args=(5,)) task_thred.start()

      結(jié)果:

      因?yàn)閭魅氲脑M是5 ,(5,)是元組的傳參操作,參數(shù)為一個(gè)元素時(shí)候一定不能忘掉了逗號(hào)。

      task_thred=threading.Thread(target=task,args=(5,))創(chuàng)建子線程并將元組(5,)傳給task(count)函數(shù),函數(shù)中count形參接收。其中target=task,target就是目標(biāo),也就是目標(biāo)函數(shù)的意思。

      task_thred.start()就是將上面創(chuàng)建的線程開啟,注意一定要開啟線程,不然線程開啟不了程序無法執(zhí)行。

      time.sleep(0.2),休眠0.2秒,看起來卡頓卡頓的,更好的看出進(jìn)程執(zhí)行的過程

      **

      2、線程之字典傳參

      **

      # TODO 字典 import threading import time def task(count): for i in range(count): print("正在工作") time.sleep(0.2) else: print("工作結(jié)束") if __name__ == '__main__': #創(chuàng)建子進(jìn)程 task_thred=threading.Thread(target=task,kwargs={"count":6}) task_thred.start()

      結(jié)果:

      task_thred=threading.Thread(target=task,kwarg={"count":6})創(chuàng)建子線程并將字典{“count”:6}傳給task(count)函數(shù),函數(shù)中count形參接收。其中target=task,target就是目標(biāo),也就是目標(biāo)函數(shù)的意思。字典就類似于json字符串,找個(gè)網(wǎng)頁(yè)單機(jī)右鍵檢查找到網(wǎng)絡(luò)下面的全部,找一個(gè)js文件打開(可以不一定是js文件,其他的也可以)刷新一下你就可以發(fā)現(xiàn)標(biāo)頭里的都是以字符串顯示的

      task_thred.start()就是將上面創(chuàng)建的線程開啟,注意一定要開啟線程,不然線程開啟不了程序無法執(zhí)行。

      time.sleep(0.2),休眠0.2秒,看起來卡頓卡頓的,更好的看出進(jìn)程執(zhí)行的過程

      **

      3、線程執(zhí)行規(guī)則

      **

      很顯然是無序的,線程和進(jìn)程都是用于資源調(diào)度,是隨機(jī)分配的,所以是都是無序的。下面通過例子來看一下。

      # TODO 線程之間執(zhí)行時(shí)無序的 import threading import time def work1(): time.sleep(1) print("當(dāng)前的線程是:",threading.current_thread().name) if __name__ == '__main__': for _ in range(5): work_thred=threading.Thread(target=work1) work_thred.start()

      結(jié)果:

      第一次執(zhí)行結(jié)果

      第二次執(zhí)行結(jié)果

      我們對(duì)比兩次的執(zhí)行結(jié)果可以發(fā)現(xiàn)第一次執(zhí)行的線程順序是: 4->5->1->3->2,而蒂維茨執(zhí)行的縣城順序是: 3->5->2->1->4,很顯然兩次的執(zhí)行順序不一致,所以線程的執(zhí)行是沒有順序的

      **

      4、測(cè)試主次線程權(quán)限,如何消除權(quán)限???又如何鞏固主線程的掌控權(quán)

      **

      測(cè)試主線程是否會(huì)等待子線程執(zhí)行完畢關(guān)閉,通過下面的例子你可以很好的了解。

      # TODO 測(cè)試主線程是否會(huì)等待子線程執(zhí)行完畢關(guān)閉 import time import threading def show_info(): for i in range(5): print("test,",i) time.sleep(1) if __name__ == '__main__': show_thted=threading.Thread(target=show_info) show_thted.start() time.sleep(1.5) print("結(jié)束")

      **

      結(jié)果:

      **

      主線程都結(jié)束了,子線程還在執(zhí)行,是不是感覺很懵。這還了得,這就相當(dāng)于誘敵深入的時(shí)候?qū)④娊心愠吠耍氵€一股勁地往前沖,這不是打亂計(jì)劃,瞎搞嗎?納悶怎么解決這個(gè)問題了。

      4.1、方法一:

      創(chuàng)建進(jìn)程的時(shí)候加入守護(hù)進(jìn)程daemon

      # TODO 測(cè)試主線程是否會(huì)等待子線程執(zhí)行完畢關(guān)閉 import time import threading def show_info(): for i in range(5): print("test,",i) time.sleep(1) if __name__ == '__main__': show_thted=threading.Thread(target=show_info,daemon=True) show_thted.start() time.sleep(1.5) print("結(jié)束")

      結(jié)果:

      我們可以發(fā)現(xiàn)主線程結(jié)束后,子進(jìn)程也停止了執(zhí)行,達(dá)到預(yù)期目的,方法可行。

      4.2、方法二

      難道必須在創(chuàng)建進(jìn)程的時(shí)候就要放入守護(hù)進(jìn)程嗎?

      # TODO 測(cè)試主線程是否會(huì)等待子線程執(zhí)行完畢關(guān)閉 import time import threading def show_info(): for i in range(5): print("test,",i) time.sleep(1) if __name__ == '__main__': show_thted=threading.Thread(target=show_info) show_thted.setDaemon(True) show_thted.start() time.sleep(1.5) print("結(jié)束")

      結(jié)果:

      這樣是不是也可以確保主線程停止后子線程跟著停止,ok,達(dá)到效果,方法可行。但是你們有沒有發(fā)現(xiàn)這樣很多余,明明一行代碼就可以實(shí)現(xiàn)的,為什么要多行代碼執(zhí)行呢,但是作為一個(gè)方法,記住還是很有必要的。

      **

      5、線程之間共享全局變量

      **

      # TODO 線程之間共享全局變量 import threading import time my_list=[] #寫入數(shù)據(jù) def write_data(): for i in range(5): my_list.append(i) time.sleep(0.1) print("write_data",my_list) # 讀取數(shù)據(jù) def read_data(): print("read_data",my_list) if __name__ == '__main__': # 創(chuàng)建寫入數(shù)據(jù)線程 write_dataThred=threading.Thread(target=write_data) # 創(chuàng)建讀取數(shù)據(jù)線程 read_dataThred=threading.Thread(target=read_data) #開啟進(jìn)程 write_dataThred.start() # 主線程等待寫入線程執(zhí)行完成以后代碼再繼續(xù)往下執(zhí)行 write_dataThred.join()# 等待子線程執(zhí)行之后再執(zhí)行下一次代碼,不加這行你會(huì)發(fā)現(xiàn)read_data 讀不到數(shù)據(jù) print("開始讀取數(shù)據(jù)")

      結(jié)果:

      read_data 哪去了??????

      從上圖可以發(fā)現(xiàn)只要重新啟動(dòng)read_dataThred線程就可以了

      你難道認(rèn)為這樣就可以了嗎,太天真了。-_-

      下面再引入一個(gè)例子。

      # TODO 線程之間共享全局變量出現(xiàn)問題 問題:線程不一致,交替拿變量 解決方法 保持線程同步,同一時(shí)刻只能有一個(gè)線程去操作全局變量 兩種方式 線程等待 + 互斥所 import threading # 創(chuàng)建函數(shù),實(shí)現(xiàn)循環(huán)100萬(wàn)次,每次全局變量加一 g_num=0 # 每次全局變量加一 def sun_num(): for i in range(1000000): global g_num g_num+=1 print("sun_num",g_num) # 每次全局變量加一 def sun_num2(): for i in range(1000000): global g_num g_num+=1 print("sun_num2", g_num) if __name__ == '__main__': sun_numThred=threading.Thread(target=sun_num) sun_num2Thred=threading.Thread(target=sun_num2) #開啟線程 sun_numThred.start() sun_num2Thred.start()

      結(jié)果:

      結(jié)果是出結(jié)果了,但是你們細(xì)看一下代碼,你們不感覺這個(gè)答案有問題嗎?

      有沒有這樣一個(gè)疑問,for循環(huán),遍歷共享變量,最后應(yīng)該是1000000和2000000啊,怎么打印出來的是1000000和1456202,而且細(xì)心的你還會(huì)發(fā)現(xiàn)每次的大男孩不一樣。想要解決問題應(yīng)該怎么辦呢?

      問題總結(jié):線程不一致,交替拿變量 解決方法 保持線程同步,同一時(shí)刻只能有一個(gè)線程去操作全局變量 兩種方式 線程等待 + 互斥所

      線程等待:join出場(chǎng)

      # TODO 線程之間共享全局變量出現(xiàn)問題 問題:線程不一致,交替拿變量 解決方法 保持線程同步,同一時(shí)刻只能有一個(gè)線程去操作全局變量 兩種方式 線程等待 + 互斥所 import threading # 創(chuàng)建函數(shù),實(shí)現(xiàn)循環(huán)100萬(wàn)次,每次全局變量加一 g_num=0 # 每次全局變量加一 def sun_num(): for i in range(1000000): global g_num g_num+=1 print("sun_num",g_num) # 每次全局變量加一 def sun_num2(): for i in range(1000000): global g_num g_num+=1 print("sun_num2", g_num) if __name__ == '__main__': sun_numThred=threading.Thread(target=sun_num) sun_num2Thred=threading.Thread(target=sun_num2) #開啟線程 sun_numThred.start() # # TODO 方法一 sun_numThred.join() sun_num2Thred.start()

      結(jié)果:

      線程等待,當(dāng)前線程等待其他線程執(zhí)行某些操作,典型場(chǎng)景就是生產(chǎn)者消費(fèi)者模式,在任務(wù)條件不滿足時(shí),等待其他線程的操作從而使得條件滿足。等到其他線程完成操作釋放后再分配線程。當(dāng)前線程獲得資源繼續(xù)執(zhí)行操作。

      **

      6、互斥鎖

      **

      ****互斥鎖 Lock():在編程中,引入了對(duì)象互斥鎖的概念,來保證共享數(shù)據(jù)操作的完整性。每個(gè)對(duì)象都對(duì)應(yīng)于一個(gè)可稱為" 互斥鎖" 的標(biāo)記,這個(gè)標(biāo)記用來保證在任一時(shí)刻,只能有一個(gè)線程訪問該對(duì)象。

      互斥鎖三步驟 ~~~ 創(chuàng)建一把鎖==》上鎖==》釋放鎖 三步走

      # TODO 互斥鎖 Lock() import threading # # TODO 創(chuàng)建一把鎖==》上鎖==》釋放鎖 三步走 # mutext=threading.Lock() # mutext.acquire() # mutext.release() #定義全局變量 g_num=0 # 創(chuàng)建一把鎖 mutext=threading.Lock() # 每次全局變量加一 def sun_num(): # TODO 上鎖 mutext.acquire() for i in range(1000000): global g_num g_num+=1 print("sun_num",g_num) # TODO 釋放鎖 mutext.release() # 每次全局變量加一 def sun_num2(): # TODO 上鎖 mutext.acquire() for i in range(1000000): global g_num g_num+=1 print("sun_num2", g_num) if __name__ == '__main__': sun_numThred=threading.Thread(target=sun_num) sun_num2Thred=threading.Thread(target=sun_num2) #開啟線程 sun_numThred.start() sun_num2Thred.start()

      python 線程 ~~ ~~~為面試開辟VIP通道~~~~~測(cè)試、死鎖、全局變量共享、守護(hù)主線程等。。。。。。

      結(jié)果:

      是不是非常神奇。

      主義事項(xiàng):

      一、互斥鎖就三步驟 1、創(chuàng)建一把鎖 2、上鎖 3、釋放鎖 。

      二、保證共享數(shù)據(jù)操作的完整性

      三、等當(dāng)前上鎖線程執(zhí)行完成,釋放鎖后其他線程才能申請(qǐng)資源

      **

      7、死鎖

      **

      死鎖是指兩個(gè)或兩個(gè)以上的線程在執(zhí)行過程中,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去

      # TODO 死鎖 import threading import time # 創(chuàng)建互斥鎖 lock=threading.Lock() def get_value(index): #上鎖 lock.acquire() print(threading.current_thread()) my_list=[3,4,7,2] # 根據(jù)下標(biāo)釋放取值 if index>=len(my_list): print("下標(biāo)越界:",index) # TODO 當(dāng)下標(biāo)越界了釋放鎖,讓后面線程繼續(xù)取值 # lock.release() return value=my_list[index] print(value) time.sleep(0.2) #釋放鎖 # lock.release() if __name__ == '__main__': #模擬大量線程取值 for i in range(30): sub_thred=threading.Thread(target=get_value,args=(i,)) sub_thred.start()

      結(jié)果:

      注釋掉釋放鎖的操作,線程剛執(zhí)行就卡住了,產(chǎn)生了死鎖。

      打開釋放所操作

      # TODO 死鎖 import threading import time # 創(chuàng)建互斥鎖 lock=threading.Lock() def get_value(index): #上鎖 lock.acquire() print(threading.current_thread()) my_list=[3,4,7,2] # 根據(jù)下標(biāo)釋放取值 if index>=len(my_list): print("下標(biāo)越界:",index) # TODO 當(dāng)下標(biāo)越界了釋放鎖,讓后面線程繼續(xù)取值 lock.release() return value=my_list[index] print(value) time.sleep(0.2) #釋放鎖 lock.release() if __name__ == '__main__': #模擬大量線程取值 for i in range(30): sub_thred=threading.Thread(target=get_value,args=(i,)) sub_thred.start()

      結(jié)果:

      1、因?yàn)槲覀兪怯梅绞絺鲄ⅲh(huán)30次,索引0~29。

      2、我們會(huì)發(fā)現(xiàn)我們?cè)谂袛嘣浇绾螅驗(yàn)獒尫沛i所以仍會(huì)輸出。

      3、加入互斥鎖解除了死鎖危機(jī)。

      覺得還不錯(cuò)的話就一鍵三連吧 __^__

      Python 任務(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)容。

      上一篇:生產(chǎn)系統(tǒng)論文(生產(chǎn)系統(tǒng)的設(shè)計(jì))
      下一篇:企業(yè)安全生產(chǎn)管理現(xiàn)狀(本公司安全生產(chǎn)現(xiàn)狀)
      相關(guān)文章
      久久精品国产亚洲Aⅴ香蕉| 国产区图片区小说区亚洲区| 亚洲欧洲中文日韩av乱码| 亚洲成A人片在线播放器| 亚洲性色成人av天堂| 亚洲国产精品成人综合色在线婷婷| 婷婷精品国产亚洲AV麻豆不片| 久久亚洲精品成人777大小说| 亚洲国产另类久久久精品黑人| 亚洲色爱图小说专区| 国产亚洲美女精品久久久2020| 国产亚洲成人久久| 久久久久亚洲?V成人无码| 亚洲熟妇无码八AV在线播放| 亚洲精品无码高潮喷水在线| 久久久青草青青亚洲国产免观| 亚洲精品美女久久久久99| 亚洲成A∨人片在线观看不卡| 亚洲gv猛男gv无码男同短文| 亚洲丁香色婷婷综合欲色啪| 亚洲人成网站在线播放影院在线| 内射干少妇亚洲69XXX| 亚洲欧洲综合在线| 亚洲乱码在线观看| 亚洲av中文无码字幕色不卡| 亚洲av无码兔费综合| 国产成人综合亚洲| 久久精品夜色噜噜亚洲A∨| 亚洲午夜福利在线观看| 久久国产亚洲电影天堂| 亚洲电影免费观看| 亚洲啪啪免费视频| 亚洲av无码一区二区三区人妖 | 久久亚洲一区二区| 亚洲综合色丁香麻豆| 国产精品亚洲自在线播放页码| 亚洲精品永久在线观看| 亚洲国产精品成人| 亚洲人成人无码网www电影首页| 婷婷精品国产亚洲AV麻豆不片| 亚洲噜噜噜噜噜影院在线播放|