多任务
有很多的场景中的事情是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的
程序中模拟多任务
import timedef sing():for i in range(3):print("正在唱歌...%d"%i)time.sleep(1)def dance():for i in range(3):print("正在跳舞...%d"%i)time.sleep(1)if __name__ == '__main__':sing()dance()
多任务的理解

- 并行:真的多任务 cpu大于当前执行的任务
- 并发:假的多任务 cpu小于当前执行的任务
通过 threading.Thread 创建多线程
线程完成多任务
import threadingimport timedef demo():# 子线程print("hello girls")time.sleep(1)if __name__ == "__main__":for i in range(5):t = threading.Thread(target=demo)t.start()
查看线程数量,通过threading.enumerate()查看
threading.enumerate() 查看当前线程的数量
验证子线程的执行与创建,第一种方法通过start方法进行创建
当调用Thread的时候,不会创建线程。
当调用Thread创建出来的实例对象的start方法的时候,才会创建线程以及开始运行这个线程。
继承Thread类创建线程 第二种方法,通过继承,重新定义run方法,调用start(),
import threadingimport timeclass A(threading.Thread):def __init__(self,name):super().__init__(name=name)def run(self):for i in range(5):print(i)if __name__ == "__main__":t = A('test_name')t.start()
多线程共享全局变量(线程间通信)
修改全局变量一定需要加global嘛?
在一个函数中,对全局变量进行修改的时候,是否要加global要看是否对全局变量的指向进行了修改,如果修改了指向,那么必须使用global,仅仅是修改了指向的空间中的数据,此时不用必须使用global
多线程共享全局变量的。
多进程不能共享全局变量,比如QQ。
进程:Java有fork,属于进程,在unix有,但是在windows里没有fork。
多线程参数-args,别忘了,
threading.Thread(target=test, args=(num,))
共享全局变量资源竞争
一个线程写入,一个线程读取,没问题,如果两个线程都写入呢?
互斥锁
当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
某个线程要更改共享数据时,先将其锁定,此时资源的状态为”锁定”,其他线程不能改变,只到该线程释放资源,将资源的状态变成”非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
创建锁mutex = threading.Lock()锁定mutex.acquire()解锁mutex.release()
死锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
import threadingimport timeclass MyThread1(threading.Thread):def run(self):# 对mutexA上锁mutexA.acquire()# mutexA上锁后,延时1秒,等待另外那个线程 把mutexB上锁print(self.name+'----do1---up----')time.sleep(1)# 此时会堵塞,因为这个mutexB已经被另外的线程抢先上锁了mutexB.acquire()print(self.name+'----do1---down----')mutexB.release()# 对mutexA解锁mutexA.release()class MyThread2(threading.Thread):def run(self):# 对mutexB上锁mutexB.acquire()# mutexB上锁后,延时1秒,等待另外那个线程 把mutexA上锁print(self.name+'----do2---up----')time.sleep(1)# 此时会堵塞,因为这个mutexA已经被另外的线程抢先上锁了mutexA.acquire()print(self.name+'----do2---down----')mutexA.release()# 对mutexB解锁mutexB.release()mutexA = threading.Lock()mutexB = threading.Lock()if __name__ == '__main__':t1 = MyThread1()t2 = MyThread2()t1.start()t2.start()
避免死锁
- 程序设计时要尽量避免
- 添加超时时间等
线程同步
天猫精灵:小爱同学
小爱同学:在
天猫精灵:现在几点了?
小爱同学:你猜猜现在几点了
多任务版udp聊天
1 创建套接字
2 绑定本地信息
3 获取对方IP和端口
4 发送、接收数据
5 创建两个线程,去执行功能
