多任務
概念:操作系統可以同時運行多個任務
併發:指的是任務數多餘cpu核數,通過操作系統的各種任務調度算法,實現用多個任務在同一時間段執行(實際上總有一些任務不在執行,因爲切換任務的速度相當快,看上去一起執行而已)
並行:指的是多核cpu情況下,多個任務的一些任務往往在同一時間點執行
線程
概念:就是一個進程內部的一條代碼執行流程
默認存在的就是主線程,新創建出來的叫做子線程
創建線程
使用threading模塊 或繼承threading.Thread
target 指定線程執行的函數名
args 指定函數的參數
enumerate() 查看當前進程中的線程列表
join() 主線程等待子線程執行完成後,才能繼續往下運行
多線程共享全局變量,如果多個線程同時對同一個全局變量操作,會出現資源競爭問題,從而數據結果會不正確
同步:就是協同步調,按預定的先後次序進行運行
互斥鎖
- 概念:某個線程要更改共享資源時,先將其鎖定,此時資源的狀態爲”鎖定”,其他線程不能更改;直到該線程釋放資源,將資源的狀態變成”非鎖定”,其他的線程才能再次鎖定該資源。互斥鎖保證了每次只有一個線程進行寫入操作,從而保證了多線程情況下數據的正確性
創建使用互斥鎖
# 創建鎖
mutex = threading.Lock()
# 鎖定
mutex.acqire()
# 釋放
mutex.release()
優缺點
優點:確保某段關鍵代碼只能有一個線程從頭到尾完整的執行
缺點:
* 阻止了多線程併發執行,包含鎖的某段代碼實際上只能以單線程模式執行,效率大大的下降了
- 由於可以存在多個鎖,不同的線程持有不同的鎖,並試圖獲取對方持有的鎖時,可能會造成死鎖
死鎖
- 概念:在線程間共享多個資源的時候,如果兩個線程分別佔有一部分資源並且同時等待對方的資源,就會造成死鎖
主要原因
沒有正確釋放
資源分配不當
避免死鎖
程序設計時要儘量避免
附加超時 時間等
線程實現簡單的多任務聊天程序
import socket
import threading
def send_msg(udp_socket):
"""獲取輸入數據,並將其發送給對方"""
msg_num = input("請輸入要發送的數據:")
dest_ip = input("請輸入對方ip地址:")
dest_port = int(input("請輸入對方端口號:"))
udp_socket.sendto(msg_num.encode(), (dest_ip, dest_port))
def recv_msg(udp_socket):
"""循環接收並顯示數據"""
while True:
recv_msug, recv_ip = udp_socket.recvfrom(1024)
print("接收到%s的數據:%s" % (str(recv_ip), recv_msug.decode("gbk")))
def main():
# 創建套接字
udp_socekt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 綁定端口
udp_socekt.bind(("", 6666))
# 創建一個子線程(收數據)
recv_thd = threading.Thread(target=recv_msg, args=(udp_socekt,))
recv_thd.start()
while True:
# 選擇功能
print("=" * 30)
print("1.發送消息")
print("2.接收消息")
print("3.退出")
print("=" * 30)
op_num = input("請輸入你要進行的操作:")
if op_num == "1":
send_msg(udp_socekt)
# elif op_num == "2":
# recv_msg(udp_socekt)
elif op_num == "3":
print("歡迎下次使用")
break
else:
print("輸入有誤!請重新輸入")
if __name__ == '__main__':
main()