22 并发编程02

线程

线程指的是在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程。

一、进程与线程的区别

进程是资源分配的最小单位,线程是CPU调度的最小单位。每一个进程中至少有一个线程。]

主进程中的线程称为主线程,其他开启的线程称为子线程

开进程的开销远远大于开线程

同一进程内的多个线程共享该进程的地址空间

  • from multiprocessing import Process p1=Process(target=task,) 换成 from threading import Thread t1=Thread(target=task,)

  • 计算密集型的多线程下不能增强性能,多进程才可以,,I/O密集型的多线程会加快程序的执行速度

  • 二、threading模块介绍

  • multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性

    1、Thread实例对象的方法

    • isAlive(): 返回线程是否活动的。

    • getName(): 返回线程名。

    • setName(): 设置线程名。

    2、threading模块提供的一些方法:

    • threading.currentThread(): 返回当前的线程变量。

    • threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。

    • threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

    • """
      进程是资源分配的最小单位,线程是CPU调度的最小单位。每一个进程中至少有一个线程。]
      
      主进程中的线程称为主线程,其他开启的线程称为子线程
      """
      
      # 如何开启线程
      from multiprocessing import Process
      
      from threading import Thread
      
      
      def task():
          print("子线程")
      
      
      if __name__ == '__main__':
          t = Thread(target=task)
          t.start()
          print("主线程")

      二、GIL全局解释器锁

    • """
      Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行
      
      
      虽然 Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。
      
      由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。
      
      
      1. python代码在解释器中执行,cpython解释器, pypy解释器
      2. GIL锁在解释器中存在,他只在cpython解释器中,pypy解释器中不存在
      3. 起一个垃圾回收线程,起一个正常执行的线程,垃圾回收还没回收完毕,另一个线程可能会抢占资源
      4. 设置了一把全局解释器锁(GIL锁),有了这把锁,就保证同一时刻,只能有一个线程执行,
          只要线程想执行,那么,就必须拿到这把GIL锁
      
      5. 如果是io密集型:选择线程
      6. 如果是计算密集型:选择进程
      """
      # print(123)
      
      # import sys
      # print(sys.argv)
      # print(sys.argv[0])
      # print(sys.argv[1])
      # print(sys.argv[2])
      # print(sys.argv[3])
      #
      # time = '2021-09'

      三、进程与线程的区别

    • from multiprocessing import Process
      
      from threading import Thread
      
      import time
      
      
      # def task():
      #     time.sleep(1)
      #     print(123)
      #
      #
      # if __name__ == '__main__':
      #     ctime = time.time()
      #     p = Process(target=task)
      #     p.start()
      #     p.join()
      #     print(time.time() - ctime)
      
      
      # def task():
      #     time.sleep(1)
      #     print(123)
      #
      #
      # if __name__ == '__main__':
      #     ctime = time.time()
      #     p = Thread(target=task)
      #     p.start()
      #     p.join()
      #     print(time.time() - ctime)
      
      
      def work():
          global n
          n=0
      
      if __name__ == '__main__':
          # n=100
          # p=Process(target=work)
          # p.start()
          # p.join()
          # print('主',n) # 毫无疑问子进程p已经将自己的全局的n改成了0,但改的仅仅是它自己的,查看父进程的n仍然为100
      
      
          n=1
          t=Thread(target=work)
          t.start()
          t.join()
          print('',n) # 查看结果为0,因为同一进程内的线程之间共享进程内的数据

      四、Thread类的其他方法

    • from threading import Thread
      import threading
      import time
      def work():
          time.sleep(1)
          global n
          n = 0
          # print(threading.currentThread())
      
      
      if __name__ == '__main__':
          t = Thread(target=work)
          t.start()
          # print(t.isAlive())
          # print(t.is_alive())
          # getName():返回线程名。
          # print(t.getName())
      
          # setName():设置线程名
          # t.setName('ly_1')
          # print(t.getName())
          # print(threading.currentThread()) # 返回当前的线程变量。
          print(threading.enumerate())

      五、守护线程

    • from threading import Thread
      import time
      
      
      def sayhi(name):
          time.sleep(2)
          print('%s say hello' % name)
      
      
      if __name__ == '__main__':
          t = Thread(target=sayhi, args=('nick',))
          t.setDaemon(True)  # 必须在t.start()之前设置
          t.start()
      
          print('主线程')
          print(t.is_alive())
          '''
          主线程
          True
          '''

      六、互斥锁(同步锁)

    • from threading import Thread,Lock
      import time
      
      def task(lock):
      
          global n
          lock.acquire()
          temp = n
          time.sleep(1)
          n = temp - 1
          # n -= 1
          lock.release()
      
      
      if __name__ == '__main__':
          n = 10
          l = []
          lock = Lock()
          for i in range(10):
              t = Thread(target=task, args=(lock, ) )
              t.start()
              l.append(t)
      
          for j in l:
              j.join()
      
          print(n)

      七、信号量

    • from threading import Thread, Semaphore
      from multiprocessing import Process, Lock
      # Semaphore:信号量可以理解为多把锁,同时允许多个线程来更改数据
      
      import time, random
      
      sm = Semaphore(2)
      
      
      def task(i):
          sm.acquire()
          print("线程:%s,进来了" % i)
          time.sleep(random.randint(1, 3))
          print("线程:%s,出去了" % i)
          sm.release()
      
      
      if __name__ == '__main__':
          for i in range(6):
              t = Thread(target=task, args=(i,))
              t.start()

      八、Event事件

    • from threading import Thread, Event
      import time
      
      
      def girl(event):
          print("某女正在恋爱中。。。")
          time.sleep(3)
          event.set()  # 发出信号
          print("某女分手了")
      
      
      def boy(i, event):
          print("屌丝:%s,正在等待某女分手..." % i)
          event.wait()  # 正在等待
          print("屌丝:%s,开始追了..." % i)
      
      
      if __name__ == '__main__':
          event = Event()
      
          t = Thread(target=girl, args=(event,))
          t.start()
      
          for i in range(10):
              t1 = Thread(target=boy, args=(i, event))
              t1.start()

       

posted @ 2021-09-02 16:23  甜甜de微笑  阅读(21)  评论(0编辑  收藏  举报