• Pyhon线程


    多线程注意点

    • 如果创建Thread时执行的函数运行结束,意味着该子线程结束。
    • 主线程结束,程序结束,主线程会等待子线程结束。
    • 子线程的开始是从调用start开始的。
    • 线程创建之后谁先执行是不确定的,可以通过添加sleep来指定顺序。
    • 查看线程个数使用len(threading.enumerate())
    import threading
    import time
    
    def test1():
        for i in range(5):
            print("....test1....%d"%i)
            time.sleep(1)
    
    def test2():
        for i in range(8):
            print("....test2....%d"%i)
            time.sleep(1)
    
    def main():
        t1 = threading.Thread(target=test1)
        t2 = threading.Thread(target=test2)
    
        t1.start()
        t2.start()
    
        while True:
            print(threading.enumerate())
            if (len(threading.enumerate())<=1):
                break        
            time.sleep(1)
    if __name__ == "__main__":
        main()

     共享全局变量

    • 共享全局变量可以方便多个线程共享数据
    • args传入一个元组作为参数
    • 不可变类型需要global声明,可变类型不需要
    import threading
    import time
    
    # 定义一个全局变量
    g_num = 100
    
    def test1(temp):
        temp.append(33)
        print("in test1 g_num=%s" % str(temp))
    
    def test2(temp):
        print("in test2 g_num=%s" % str(temp))
    
    g_nums = [11, 22]
    
    def main():
        # target指定将来哪个线程去哪个函数执行代码
        # args指定将来调用函数的参数
        t1 = threading.Thread(target=test1, args=(g_nums,))
        t2 = threading.Thread(target=test2, args=(g_nums,))
    
        t1.start()
        time.sleep(1)
    
        t2.start()
        time.sleep(1)
    
        print("in main g_num=%s" % str(g_nums))
    
    if __name__ == "__main__":
        main()

    共享全局变量造成资源竞争

    • 不同线程都要修改某个变量,比如都要执行g_num+=1,这个过程分为三步:
      1. 获得g_num的值
      2. 给这个值加一
      3. 把加一后的值赋给g_num
    • 如果第一个线程执行了前两步,获得g_num=0,然后加一,但还没有赋值给n_num就进入休眠,轮到第二个线程执行,获得的g_num的值还是0,加一后得到1,还没执行第三步,又轮到第一个线程,这时线程1会接着上次的操作,直接从第三步开始,得到g_num=1;再次轮到第二个线程,也接着从第三步开始,得到g_num=1,两个线程结束后本该得到g_num=2,这里确得到1.
    • 为了解决上述问题,引入互斥锁的概念,使用threading模块中的Lock,给可能冲突的代码段上锁、解锁。从而避免资源竞争引发的错误。
    • 当存在多个锁时,可能存在死锁问题,两个线程都等待对方解锁,程序设计中要尽量避免死锁。
    import threading
    import time
    
    # 定义一个全局变量
    g_num = 0
    
    def test1(num):
        global g_num
        for i in range(num):
            mutex.acquire()
            g_num += 1
            mutex.release()
        print("in test1 g_num=%d" % g_num)
    
    def test2(num):
        global g_num
        for i in range(num):
            mutex.acquire()
            g_num += 1
            mutex.release()
        print("in test2 g_num=%d" % g_num)
    
    
    mutex = threading.Lock()
    def main():
        # target指定将来哪个线程去哪个函数执行代码
        # args指定将来调用函数的参数
        t1 = threading.Thread(target=test1, args=(1000000,))
        t2 = threading.Thread(target=test2, args=(1000000,))
    
        t1.start()
        t2.start()
    
        while len(threading.enumerate()) != 1:
            time.sleep(1)
    
        print("in main g_num=%d" % g_num)
    
    if __name__ == "__main__":
        main()

  • 相关阅读:
    Spring_Bean的配置方式
    Nginx Ingress设置账号密码
    2.2.4 加减运算与溢出
    2.2.5-2 补码乘法
    2.2.3 移位运算
    flask钩子函数
    flask的cookie、session
    循环冗余校验码
    海明校验码
    python中的 __call__()
  • 原文地址:https://www.cnblogs.com/yunxiaofei/p/11054585.html
Copyright © 2020-2023  润新知