高級(jí)python編程 ---5 多任務(wù)-線程

1?線程簡(jiǎn)介

1.1多任務(wù)

簡(jiǎn)單說(shuō),同一時(shí)間上操作系統(tǒng)可以運(yùn)行多個(gè)任務(wù)。單核CPU理論上只能執(zhí)行單個(gè)任務(wù),多任務(wù)只是多個(gè)程序的輪流執(zhí)行而已(時(shí)間片輪轉(zhuǎn))

并行:多任務(wù)由不同CPU進(jìn)行執(zhí)行,每個(gè)都相互一一對(duì)應(yīng)(任務(wù)數(shù)量小于或等于核心數(shù)量)

并發(fā):多任務(wù)由單個(gè)或多個(gè)CPU實(shí)現(xiàn)(任務(wù)數(shù)量大于核心數(shù)量)

線程:執(zhí)行任務(wù)的東西,線程的運(yùn)行是隨機(jī)的。

1.2簡(jiǎn)單實(shí)例

簡(jiǎn)單實(shí)現(xiàn)多線程的執(zhí)行,實(shí)例中唱歌和跳舞可實(shí)現(xiàn)同步執(zhí)行

圖1? ? 多線程實(shí)例

如果創(chuàng)建Thread時(shí)執(zhí)行的函數(shù),運(yùn)行結(jié)束意味著?這個(gè)子線程結(jié)束;主線程結(jié)束會(huì)結(jié)束所有程序。

threading.enumerate()?????查看當(dāng)前的線程信息

2?線程進(jìn)階

2.1?繼承類方法實(shí)現(xiàn)

圖2? ? 繼承方法

2.2多線程共享全局變量

在一個(gè)函數(shù)中,對(duì)全局變量進(jìn)行修改時(shí),如果對(duì)全局變量的指向進(jìn)行修改,則需要使用global;如果僅僅是指向的空間所代表的數(shù)據(jù),則不需要使用。

圖3? ? 線程享全局變量

2.3?共享全局變量(資源競(jìng)爭(zhēng)問(wèn)題)

圖4? ? 問(wèn)題

當(dāng)某一進(jìn)程運(yùn)算量很大時(shí),在進(jìn)程1還未結(jié)束時(shí)就跳出來(lái)了,并且未把計(jì)算的值代入全局變量,跳出了執(zhí)行后續(xù)的進(jìn)程,以此往復(fù),造成數(shù)據(jù)的不對(duì)。

原則性:某事情不做完就不會(huì)結(jié)束

2.3.1?同步

同步,按預(yù)定的先后次序進(jìn)行運(yùn)行

2.3.2?互斥鎖

當(dāng)多個(gè)線程幾乎同時(shí)修改某一個(gè)共享數(shù)據(jù)的時(shí)候,需要進(jìn)行同步控制。互斥鎖為資源引入一個(gè)狀態(tài):鎖定/非鎖定。保證資源修改的進(jìn)程。

同一把鎖只能上一次鎖,待解鎖后方可進(jìn)行再次上鎖。

2.3.2.1互斥鎖解決方法

圖5? ? 互斥鎖
圖6? ? 互斥鎖結(jié)果
圖7? ? 另一種加鎖
圖8? ? 加鎖的結(jié)果

2.3.2.2?死鎖

同一時(shí)間,多個(gè)進(jìn)程互相對(duì)已上鎖的資源對(duì)象進(jìn)行使用。

避免死鎖的方法:添加超時(shí)時(shí)間;程序設(shè)計(jì)時(shí)避免(銀行家算法)

銀行家算法:在有限計(jì)算資源下,為所有線程分?jǐn)偞笾碌馁Y源,并可滿足剩余資源能實(shí)現(xiàn)某一進(jìn)程的所有任務(wù),待這一進(jìn)程結(jié)束又可繼續(xù)滿足其他進(jìn)程的任務(wù),以此往復(fù),實(shí)現(xiàn)所有進(jìn)程的任務(wù)。

3?多線程版本(udp聊天)

3.1?客戶端代碼

```

# -*-coding:utf-8 -*-

import socket

import threading

def SendMessage(udp_multi_socket):

? ? server_dest = ("192.168.137.1", 7878)

? ? while True:

? ? ? ? send_data = input ("請(qǐng)輸入想要發(fā)送的內(nèi)容:")

? ? ? ? if send_data is 'q':break

? ? ? ? udp_multi_socket.sendto (send_data.encode ("utf-8"), server_dest)

def RecvMessage(udp_multi_socket):

? ? #server_dest = ("192.168.137.1", 7878)

? ? while True:

? ? ? ? rec_data = udp_multi_socket.recvfrom(1024)

? ? ? ? print(rec_data[0].decode("utf-8"))

def main():

? ? udp_multi_socket = socket.socket (socket.AF_INET,socket.SOCK_DGRAM)

? ? udp_multi_socket.bind (("192.168.137.1", 8080))

? ? t1 = threading.Thread(target=SendMessage, args=(udp_multi_socket,))

? ? t2 = threading.Thread(target=RecvMessage, args=(udp_multi_socket,))

? ? t1.start()

? ? t2.start()

if __name__ == '__main__':

? ? main()

```

3.2 服務(wù)端代碼

其實(shí)服務(wù)端可以下載使用網(wǎng)絡(luò)調(diào)試助手來(lái)實(shí)現(xiàn)服務(wù)器(另一臺(tái)機(jī)器)的模擬。在這里,可以在本機(jī)的另一端口來(lái)實(shí)現(xiàn)相似功能,其代碼與客戶端相同,只是端口進(jìn)行了調(diào)換,實(shí)際情況中,端口和IP均會(huì)有所變化。

```

# -*-coding:utf-8 -*-

import socket

import threading

def SendMessage(udp_multi_socket):

? ? server_dest = ("192.168.137.1", 8080)

? ? while True:

? ? ? ? send_data = input ("請(qǐng)輸入想要發(fā)送的內(nèi)容:")

? ? ? ? if send_data is 'q':break

? ? ? ? udp_multi_socket.sendto (send_data.encode ("utf-8"), server_dest)

def RecvMessage(udp_multi_socket):

? ? #server_dest = ("192.168.137.1", 7878)

? ? while True:

? ? ? ? rec_data = udp_multi_socket.recvfrom(1024)

? ? ? ? print(rec_data[0].decode("utf-8"))

def main():

? ? udp_multi_socket = socket.socket (socket.AF_INET,socket.SOCK_DGRAM)

? ? udp_multi_socket.bind (("192.168.137.1", 7878))

? ? t1 = threading.Thread(target=SendMessage, args=(udp_multi_socket,))

? ? t2 = threading.Thread(target=RecvMessage, args=(udp_multi_socket,))

? ? t1.start()

? ? t2.start()

if __name__ == '__main__':

? ? main()

```

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容