第二十章 Python多任务-线程

1.多任务

  • 有很多的场景中的事情是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的

2. 程序中模拟多任务

import time

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

3.多任务的理解

  • 并行:真的多任务 cpu大于当前执行的任务
  • 并发:假的多任务 cpu小于当前执行的任务

4.线程完成多任务

import threading
import time

def demo():
    # 子线程
    print("hello girls")
    time.sleep(1)
    
if __name__ == "__main__":
    for i in range(5):
        t = threading.Thread(target=demo)
        t.start()   

5. 查看线程数量

threading.enumerate() 查看当前线程的数量

6.验证子线程的执行与创建

  • 当调用Thread的时候,不会创建线程。
  • 当调用Thread创建出来的实例对象的start方法的时候,才会创建线程以及开始运行这个线程。

7.继承Thread类创建线程

import threading
import time

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

8.多线程共享全局变量(线程间通信)

  • 修改全局变量一定需要加global嘛?
  • 在一个函数中,对全局变量进行修改的时候,是否要加global要看是否对全局变量的指向进行了修改,如果修改了指向,那么必须使用global,仅仅是修改了指向的空间中的数据,此时不用必须使用global

9.多线程参数-args

threading.Thread(target=test, args=(num,))

10. 共享全局变量资源竞争

  • 一个线程写入,一个线程读取,没问题,如果两个线程都写入呢?

11.互斥锁

  • 当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
  • 某个线程要更改共享数据时,先将其锁定,此时资源的状态为"锁定",其他线程不能改变,只到该线程释放资源,将资源的状态变成"非锁定",其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

创建锁
mutex = threading.Lock()
锁定
mutex.acquire()
解锁
mutex.release()

12.死锁

  • 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
import threading
import time

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

13.避免死锁

  • 程序设计时要尽量避免
  • 添加超时时间等

14.线程同步

  • 天猫精灵:小爱同学
  • 小爱同学:在
  • 天猫精灵:现在几点了?
  • 小爱同学:你猜猜现在几点了

15. 多任务版udp聊天

  • 1 创建套接字
  • 2 绑定本地信息
  • 3 获取对方IP和端口
  • 4 发送、接收数据
  • 5 创建两个线程,去执行功能
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。