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í)行

如果創(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多線程共享全局變量
在一個(gè)函數(shù)中,對(duì)全局變量進(jìn)行修改時(shí),如果對(duì)全局變量的指向進(jìn)行修改,則需要使用global;如果僅僅是指向的空間所代表的數(shù)據(jù),則不需要使用。

2.3?共享全局變量(資源競(jìng)爭(zhēng)問(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互斥鎖解決方法




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()
```