• 多线程


    多线程

    1线程理论知识

    • 什么是线程
      • 线程就是一条流水线
      • 进程 : 划分空间,加载资源,静态的.
      • 线程 : 执行代码,执行能力,动态的
    • 线程VS进程
      • 开启多进程开销非常大,开启线程开销非常小
      • 开启多进程的速度慢,开启多线程速度快
      • 进程之间数据不能直接共享,通过队列可以,同一进程下的线程之间的数据可以共享
    • 多线程的应用场景介绍
      • 并发:一个cpu来回切换,多进程并发,多线程的并发
      • 多进程并发:开启多个进程,每个进程里面的主线程执行任务
      • 多线程并发:开启一个进程,进程里面的多个线程执行任务

    2.开启线程的两种方式

    • 第一种方式

      • # 第一种方式
        # from threading import Thread
        #
        # def task(name):
        #     print(f'{name} is running')
        #
        # if __name__ == '__main__':
        #     t = Thread(target=task,args=('mcsaoQ',))
        #     t.start()
        #
        #     print('主线程')
        
    • 第二种方式

      • from threading import Thread
        
        
        class MyThread(Thread):
        
        
            def run(self):
                print(f'{self.name} is running')
        
        
        if __name__ == '__main__':
            t = MyThread()
            t.start()
        
            print('主线程')
        

    3.线程与进程之间的对比

    • 速度的对比

      • from threading import Thread
        
        
        def task(name):
            print(f'{name} is running')
        
        
        
        if __name__ == '__main__':
            t = Thread(target=task,args=('mcsaoQ',))
            t.start()
        
            print('主线程')
        
        '''
        线程绝对要比进程要快:
            mcsaoQ is running
            主线程
        '''
        
    • pid

      • # pid 进程号
        from threading import Thread
        import os
        
        def task():
            print(f'子线程: {os.getpid()}')
        
        
        
        if __name__ == '__main__':
            t = Thread(target=task,)
            t.start()
        
            print(f'主线程: {os.getpid()}')
        
    • 线程之间的共享资源

      • # from threading import Thread
        #
        # x = 1000
        #
        # def task():
        #     global x
        #     x = 0
        #
        #
        # if __name__ == '__main__':
        #     t = Thread(target=task)
        #     t.start()
        #     # t.join()
        #     print(f'主线程: {x}')
        
        
        
        
        # from threading import Thread
        # import time
        # x = 1000
        #
        # def task():
        #     time.sleep(3)
        #     print('子线程....')
        #
        #
        # def main():
        #     print('111')
        #     print('222')
        #     print('333')
        #
        # #
        # # task()
        # # main()
        #
        # if __name__ == '__main__':
        #     t = Thread(target=task)
        #     t.start()
        #     # t.join()
        #     main()
        

    4.线程的其他方法

    • # from threading import Thread
      # import threading
      # import time
      #
      #
      # def task(name):
      #     time.sleep(1)
      #     print(f'{name} is running')
      #     print(threading.current_thread().name)
      #
      #
      #
      # if __name__ == '__main__':
      #     for i in range(5):
      #         t = Thread(target=task,args=('mcsaoQ',))
      #         t.start()
      #     # 线程对象的方法:
      #     # time.sleep(1)
      #     # print(t.is_alive())  # 判断子线程是否存活  ***
      #     # print(t.getName())  # 获取线程名
      #     # t.setName('线程111')
      #     # print(t.getName())  # 获取线程名
      #
      #     # threading模块的方法:
      #     # print(threading.current_thread().name)  # MainThread
      #     # print(threading.enumerate())  # 返回一个列表 放置的是所有的线程对象
      #     print(threading.active_count())  # 获取活跃的线程的数量(包括主线程)
      #     print('主线程')
      

    5.守护线程

    • 守护:子线程守护主线程,

    • 结束条件:守护线程必须等待主线程结束才结束,主线程必须等所有的非守护线程结束才能结束

    • from threading import Thread
      
      import time
      
      def foo():
          print(123)
          time.sleep(3)
          print("end123")
      def bar():
          print(456)
          time.sleep(1)
          print("end456")
      if __name__ == '__main__':
          t1=Thread(target=foo)
          t2=Thread(target=bar)
      
          t1.daemon = True
          t1.start()
          t2.start()
          print("main-------")
      

    6.互斥锁(同步锁)

    7.死锁现象,递归锁

    • 进程由死锁与递归锁,与线程同理,

    • 死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁

      • from threading import Thread
        from threading import Lock
        import time
        
        lock_A = Lock()
        lock_B = Lock()
        
        
        class MyThread(Thread):
        
            def run(self):
                self.f1()
                self.f2()
        
            def f1(self):
                lock_A.acquire()
                print(f'{self.name}拿到A锁')
        
                lock_B.acquire()
                print(f'{self.name}拿到B锁')
                lock_B.release()
        
                lock_A.release()
        
            def f2(self):
                lock_B.acquire()
                print(f'{self.name}拿到B锁')
                time.sleep(0.1)
        
                lock_A.acquire()
                print(f'{self.name}拿到A锁')
                lock_A.release()
        
                lock_B.release()
        
        if __name__ == '__main__':
            for i in range(3):
                t = MyThread()
                t.start()
        
            print('主....')
        
    • 解决死锁的方法:递归锁,在python中为了支持同一线程中多次请求同一资源,Python提供了可重入锁RLock

      • RLock内部维护着一个Lock和counter变量,counter记录了acquire的次数,从而使得资源可以被多次require,直到一个线程所有的acquire都被release,其他线程才能获取资源,上面的例子如果使用RLock代替Lock,则不会发生死锁:

      • from threading import Thread
        from threading import RLock
        import time
        
        lock_A = lock_B = RLock()
        
        
        class MyThread(Thread):
            
            def run(self):
                self.f1()
                self.f2()
            
            def f1(self):
                lock_A.acquire()
                print(f'{self.name}拿到A锁')
                
                lock_B.acquire()
                print(f'{self.name}拿到B锁')
                lock_B.release()
                
                lock_A.release()
            
            def f2(self):
                lock_B.acquire()
                print(f'{self.name}拿到B锁')
                time.sleep(0.1)
                
                lock_A.acquire()
                print(f'{self.name}拿到A锁')
                lock_A.release()
                
                lock_B.release()
        
        
        if __name__ == '__main__':
            for i in range(10):
                t = MyThread()
                t.start()
            
            print('主....')
        

    8.信号量

    • Semaphore管理一个内置的计数器,每当调用acquire()时内置计数器+1,调用release()时内置计数器-1,计数器不能小于0,当计数器为0时,acquire()将阻塞线程直到其他线程调用release(),

    • from threading import Thread
      from threading import Semaphore
      from threading import current_thread
      import time
      import random
      
      sem = Semaphore(5)
      
      def go_public_wc():
          sem.acquire()
          print(f'{current_thread().getName()} 上厕所ing')
          time.sleep(random.randint(1,3))
          sem.release()
      
      
      if __name__ == '__main__':
          for i in range(20):
              t = Thread(target=go_public_wc)
              t.start()
      
  • 相关阅读:
    01-时间复杂度、对数器(python)、冒泡、选择、递归实质、归并、小和问题、逆序对、mid
    2017.07.07 IT项目管理笔记整理 第八章 软件项目质量管理
    2017.07.07 IT项目管理笔记整理 第七章 软件项目资源管理
    2017.07.07 IT项目管理笔记整理 第六章软件项目配置管理
    2017.07.06 IT项目管理笔记整理 第五章软件项目风险管理
    2017.07.06 IT项目管理笔记整理 第四章软件项目进度管理
    2017.07.06 IT项目管理笔记整理 第三章软件项目成本管理
    2017.07.06 IT项目管理笔记整理 第二章软件项目需求管理
    2017.06.29数据挖掘基础概念第十,十一章
    2017.06.29数据挖掘基础概念第六,八,九章
  • 原文地址:https://www.cnblogs.com/W-Y-C/p/11238755.html
Copyright © 2020-2023  润新知