Python多线程编程,线程锁

发布时间:2019-03-10 19:53:53编辑:auto阅读(2176)

     

    多线程

    • 什么是线程?

      1. 线程也是一种多任务的编程方法,可以利用计算机多核资源完成程序的并发运行。
      2. 线程又被称为轻量级进程
    • 线程的特征

      1. 线程是计算机多核分配的最小单位
      2. 一个进程可以包含多个线程
      3. 线程也是一个运行的过程,消耗计算机资源,多个线程共享进程的资源和空间
      4. 线程的创建删除消耗的资源都远远比进程小
      5. 多个线程之间执行互不干扰
      6. 线程也有自己的特有属性,比如指令集ID

    threading 模块创建线程

     

    • t=threading.Thread()

      • 功能:创建线程对象

      • 参数

        • name:线程名称,如果为空则为默认值,Tread-1,Tread-2,Tread-3
        • target:线程函数
        • args:元组,给线程函数按照位置传参
        • kwargs:字典,给县城函数按照键值传参
    • t.start():启动线程,自动运行线程函数

    • t.join([timeout]):回收进程

    • t.is_alive():查看线程状态

    • t.name():查看线程名称

    • t.setName():设置线程名称

    • t.daemon属性:默认主线成退出不影响分支线程继续执行,如果设置为True则分支线程随着主线程一起退出

      • 设置方法

        • t.daemon = True

        • t.setDaemon(Ture)

           
    •  1 #!/usr/bin/env python3
       2 from threading import Thread
       3 from time import sleep
       4 import os
       5  6 # 创建线程函数
       7 def music():
       8     sleep(2)
       9     print("分支线程")
      10 11 t = Thread(target = music)
      12 # t.start()   # ******************************
      13 print("主线程结束---------")
      14 15 '''没有设置的打印结果
      16 主线程结束---------
      17 分支线程
      18 '''
      19 20 '''设置为True打印结果
      21 主线程结束---------
      22 '''

       

    • threading.currentThread:获取当前线程对象

     

    @此处代码示意子线程共享同一个进程内的变量

     
     1   #!/usr/bin/env python3
     2   from threading import Thread
     3   from time import sleep
     4   import os
     5   
     6   # 创建线程函数
     7   def music():
     8       global a
     9       print("a=",a)
    10       a = 10000
    11       for i in range(5):
    12           sleep(1)
    13           print("1212")
    14   
    15   a = 1
    16   t = Thread(target = music)
    17   t.start()
    18   t.join()
    19   print("主线程的a =",a)

     

    创建自己的线程类

    考察点:类的使用,调用父类的__init__方法,函数*传参和**传参

      
     1  
     2   
     3 from threading import Thread
     4 import time
     5  6 class MyThread(Thread):
     7     name1 = 'MyThread-1'
     8     def __init__(self,target,args=(), kwargs={}, name = 'MyThread-1'):
     9         super().__init__()
    10         self.name = name
    11         self.target = target
    12         self.args = args
    13         self.kwargs = kwargs
    14     def run(self):
    15         self.target(*self.args,**self.kwargs)
    16 17 def player(song,sec):
    18     for i in range(2):
    19         print("播放 %s:%s"%(song,time.ctime()))
    20         time.sleep(sec)
    21 22 t =MyThread(target = player, args = ('亮亮',2))
    23 24 t.start()
    25 t.join()
    26

     

    线程通信

    通信方法:由于多个线程共享进程的内存空间,所以线程间通信可以使用全局变量完成

    注意事项:线程间使用全局变量往往要同步互斥机制保证通信的安全

    线程同步互斥方法

    • event

    • e = threading.Event():创建事件对象

    • e.wait([timeout]):设置状态,如果已经设置,那么这个函数将阻塞,timeout为超时时间

    • e.set:将e变成设置状态

    • e.clear:删除设置状态

        
    import threading
    from time import sleep
    
    def fun1():
        print("bar拜山头")
        global s
        s = "天王盖地虎"
    
    def fun2():
        sleep(4)
        global s
        print("我把限制解除了")
        e.set()     # 解除限制,释放资源
    
    def fun3():
        e.wait() # 检测限制
        print("说出口令")
        global s
        if s == "天王盖地虎":
            print("宝塔镇河妖,自己人")
        else:
            print("打死他")
        s = "哈哈哈哈哈哈"
    
    # 创建同步互斥对象
    e = threading.Event()
    # 创建新线程
    f1 = threading.Thread(target = fun1)
    f3 = threading.Thread(target = fun3)
    f2 = threading.Thread(target = fun2)
    # 开启线程
    f1.start()
    f3.start()
    f2.start()
    #准备回收
    f1.join()
    f3.join()
    f2.join()

     

    线程锁

    • lock = threading.Lock():创建锁对象
    • lock.acquire():上锁
    • lock.release():解锁

    也可以用过with来上锁

      
    1 with lock:
    2     ...
    3     ...

     

     

    @需要了解!!!

    • Python线程的GIL问题(全局解释器)

      python---->支持多线程---->同步互斥问题---->加锁解决---->超级锁(给解释器加锁)---->解释器同一时刻只能解释一个线程--->导致效率低下

    • 后果

      一个解释器同一时刻只能解释执行一个线程,所以导致Python线程效率低下,但是当遇到IO阻塞时线程会主动让出解释器,因此Pyhton线程更加适合高延迟的IO程序并发

    • 解决方案

      • 尽量使用进程完成并发(和没说一样)
      • 不适当用C解释器 (用C# ,JAVA)
      • 尽量使用多种方案组合的方式进行并发操作,线程用作高延迟IO
    作者:Banl
    ----------------------------------------------------------------------

    个性签名:青春用来挥霍,白头不知所措!

    如果这篇文章对你有些帮助,记得在右下角点个“推荐”,拜谢!

     

     

     

     

     

     

     

     

     

关键字