简单地说,就是操作系统可以同时运行多个任务。实现多任务有多种方式,线程、进程、协程。
threading 穿线,穿过,编制
thread 线,思路
target 目标
args 参数
enumerate 列举,枚举
acquire 获得,取得,学到
release 释放, 发射,让与
mutex 互斥
a = (1) 不是一个元组
a = (1,) 是一个元组
args = ( ,) 传递参数的时候,一定要加上逗号
t.join( ) 保证线程运行完再运行后面的代码
谁先上锁,谁就先执行,谁后上锁,谁就后执行
并行和并发的区别?
并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的
真的多任务叫并行,假的多任务叫并发。
什么是线程?
可以简单理解为同一进程中有多个计数器,每个线程的执行时间不确定,而每个进程的时间片相等,线程是操作系统调度执行的最小单位.
线程的创建步骤
Import threading
# 创建一个线程对象
t1 = threading.Thread(target=func_name, args=(num,), name=”子线程名字”)
# 创建一个线程并启动
t1.start()
# 等待子线程执行完毕之后再继续向下执行主线程
t1.join()
备注:主线程会等待子线程结束之后才会结束,主线程一死,子线程也会死。线程的调度是随机的,并没有先后顺序。
枚举函数enumerate的用法
enumerate()是python的内置函数,在字典上是枚举、列举的意思。用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。通过threading.enumerate()就可以获取线程列表。
thread_listt = threading.enumerate()
print(thread_listt)
互斥锁的运用
由于多线程之间共享全局变量就会导致出现资源竞争的问题,为了避免这种竞争出现,利用互斥锁可以实现线程同步。
# 创建锁 Mutex = threading.Lock() # 加锁 Mutex.acquire() # 释放锁 Mutex.release()
什么是死锁?(了解)
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,尽管死锁很少发生,但一旦发生就会造成应用的停止响应。
使用线程构造一个同步聊天器:
# udp同步聊天器,使用线程 import threading import socket def recv(udp_socket): # 循环接收信息 while True: recv_data = udp_socket.recvfrom(1024) print(recv_data) def send(udp_socket, local_ip, local_port): # 循环发送信息 while True: send_data = input("请输入要发送的信息:") udp_socket.sendto(send_data.encode("utf-8"), (local_ip, local_port)) def main(): # 创建套接字 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 绑定本地信息 local_ip = input("请输入对方ip:") local_port = int(input("请输入端口:")) local_add = ("", 8989) udp_socket.bind(local_add) # 创建线程,运行接收和发送函数 t1 = threading.Thread(target=recv, args=(udp_socket,)) t2 = threading.Thread(target=send, args=(udp_socket, local_ip, local_port)) t1.start() t2.start() if __name__ == '__main__': main()