python之线程学习(二)

引文

上一篇博客留下了一个问题,如何解决资源抢占问题,接下来将会给出解决方法

互斥锁与死锁

互斥锁

当多个进程几乎同时修改某一个共享数据时,我们需要进行同步控制,否则会造成读脏数据

  • 原理
    • 当某个进程要修改共享数据时,我们先将其锁定,此时资源为“锁定”状态,其他线程不能改变,等到资源得到释放之后,才能被其他线程锁定并修改
    • 互斥锁保证了每次只有一个线程进行写入操作,从而保证了在多个线程的情况下共享数据的正确性
  • 代码示例
    import threading
    import time
    
    
    def a(x, mutex):
        global num
        # 上锁
        mutex.acquire()
        for i in range(x):
            num += 1
        # 释放
        mutex.release()
        print(f'a: {num}')
    
    
    def b(x, mutex):
        global num
        # 上锁
        mutex.acquire()
        for i in range(x):
            num += 1
        # 释放
        mutex.release()
        print(f'b: {num}')
    
    
    if __name__ == '__main__':
        mutex = threading.Lock()
        num = 100
        t1 = threading.Thread(target=a, args=(1000000, mutex))
        t2 = threading.Thread(target=b, args=(1000000, mutex))
        t1.start()
        t2.start()
        # 等待1秒,之后子线程已结束
        time.sleep(1)
        print(num)
    
    

死锁

  • 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁
  • 如果重复上了很多个Lock锁也会造成死锁状态
  • 代码示例
    import threading
    
    
    def a(mutex):
        mutex.acquire()
        mutex.acquire()
        print('a')
        mutex.release()
        mutex.release()
    
    
    if __name__ == '__main__':
        mutex = threading.Lock()
        t = threading.Thread(target=a, args=(mutex,))
        t.start()
        print('main')
        
    
  • 如果将Lock锁换成RLock锁,就会避免死锁问题
  • 添加超时时间也可以避免死锁

注意: 程序设计时要尽量避免死锁问题

线程同步

threading里面有一个Condition类,这个类里有两个方法,分别是__enter____exit__,所以使用这个类的时候可以以with的形式出现。使用Condition类可以实现线程同步

  • 以一个简单的对话举例说明:
    天猫精灵:小爱同学!
    小爱同学:我在!
    天猫精灵:你想去哪里?
    小爱同学:我想去你的心里!
  • 代码示例
    import threading
    from threading import Condition
    
    
    class TianMao(threading.Thread):
        def __init__(self, con):
            super().__init__(name='天猫精灵')
            self.con = con
    
        def run(self):
            with self.con:
                print(f"{self.name}:小爱同学!")
                # 唤醒
                self.con.notify()
                # 等待
                self.con.wait()
                print(f"{self.name}:你想去哪里?")
                # 唤醒
                self.con.notify()
    
    
    class XiaoAi(threading.Thread):
        def __init__(self, con):
            super().__init__(name='小爱同学')
            self.con = con
    
        def run(self):
            with self.con:
                # 等待
                self.con.wait()
                print(f"{self.name}:我在!")
                # 唤醒
                self.con.notify()
                # 等待
                self.con.wait()
                print(f"{self.name}:我想去你心里!")
    
    
    if __name__ == '__main__':
        con = threading.Condition()
        xiaoai = XiaoAi(con)
        tianmao = TianMao(con)
        xiaoai.start()
        tianmao.start()
    
    

当天猫精灵说完第一句话时,就会唤醒正在等待的小爱同学,之后天猫精灵就处于等待状态,以此循环直到对话结束

多任务版udp聊天

学了多线程,也没有用在一个实际的例子里,现在开发一款简单的多任务版udp聊天,可以同时发送信息和接收信息

  • 代码示例
    import socket
    import threading
    
    
    def send_info(udp_socket):
        while True:
            # 3、发送信息
            content = input('请输入要发送的内容:').encode('gbk')
            udp_socket.sendto(content, ('192.168.1.3', 8080))
    
    
    def recv_info(udp_socket):
        while True:
            # 4、接收信息
            infos, addr = udp_socket.recvfrom(1024)
            print(f"{addr}:{infos.decode('gbk')}")
    
    
    def udp_chat():
        # 1、创建套接字
        udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # 2、绑定本地ip和port
        udp_socket.bind(("192.168.1.3", 7890))
        # 3、创建发送信息线程
        t1 = threading.Thread(target=send_info, args=(udp_socket,))
        # 4、创建接收信息线程
        t2 = threading.Thread(target=recv_info, args=(udp_socket,))
    
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        udp_chat()
        
    

最后,有喜欢博主写的内容的伙伴可以点赞收藏加关注哦!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员陈_明勇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值