• 并发编程(线程)——前言理论,开启线程的两种方式,线程对象join方法,同一个进程下的多个线程数据共享,线程对象及其他方法,守护线程,线程互斥锁,GIL全局解释器锁理论


    一、线程理论

    计算机相当于大工厂,工厂里有一个个的车间(进程),有很多人(线程)干不同的事
    真正干活的是线程--》线程是cup调度的最小单位
    进程是资源分配的最小单位,线程是CPU调度的最小单位。每一个进程中至少有一个线程
    线程开销更小,更轻量级

    二、开启线程的两种方式

    1、函数式

    #第一种
    from threading import Thread
    import time
    
    def task():
        print('开始')
        time.sleep(1)
        print('结束')
    
    
    if __name__ == '__main__':
        t=Thread(target=task,) # 实例化得到一个对象
        t.start() # 对象.start()启动线程
        print(''

    2、通过类继承方式

    #第二种
    from threading import Thread
    import time
    
    class MyThread(Thread):
        def run(self):
            print('开始')
            time.sleep(1)
            print('结束')
    
    if __name__ == '__main__':
        t=MyThread()
        t.start()
        print('')

    三、线程对象join方法

    from threading import Thread
    
    import time
    def task(n):
        print('开始')
        time.sleep(n)
        print('结束')
    
    
    if __name__ == '__main__':
        t=Thread(target=task,args=(2,))
        t.start()
    
    
        t1=Thread(target=task,args=(3,))
        t1.start()
    
    
        t.join()  # 等待子进程执行结束
        t1.join()
        print('')

    四、同一个进程下多个线程数据共享

    from threading import Thread
    
    import time
    
    money = 99
    
    
    def task(n):
        global money
        money=n
        print('开始')
        # time.sleep(n)
        print('结束')
    
    
    if __name__ == '__main__':
        t = Thread(target=task, args=(2,))
        t.start()
    
        t1 = Thread(target=task, args=(66,))
        t1.start()
    
    
        t.join()
        t1.join()
        print(money)
        print('')

    五、线程对象及其他方法

    from threading import Thread, current_thread,active_count
    import time
    
    
    def task():
        print('开始')
        print(current_thread().name)   # 线程名字
        time.sleep(1)
        print('结束')
    
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task,name='egon')
        t2 = Thread(target=task)
        t1.start()
        t2.start()
        print(active_count())  # 打印出3 ,开了两个线程,还有一个主线程
    from threading import Thread, current_thread,active_count
    import time
    import os
    
    
    def task(n):
        print('开始')
        print(current_thread().name)   # 线程名字
        # 如果打印进程id号,会是什么
        print(os.getpid())
        time.sleep(n)
        print('结束')
    
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task,name='egon',args=(2,))
        t2 = Thread(target=task,args=(8,))
        t1.start()
        t2.start()
        t1.join()
        print('---------',t1.is_alive())
        print('---------',t2.is_alive())
    
        # 当作线程id号
        print('*********',t1.ident)
        print('*********',t2.ident)
    
        print(os.getpid())
        print(active_count())  # 打印出3 ,开了两个线程,还有一个主线程

    总结必知:

    1 线程t.name  t.getName()
    2 当前进程下有几个线程存活active_count
    3 t1.is_alive() 当前线程是否存活
    4 t1.ident  当作是线程id号

    六、守护线程

    from threading import Thread, current_thread,active_count
    import time
    import os
    
    
    def task(n):
        print('开始')
        time.sleep(n)
        # print('-----',active_count())
        print('结束')
    
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task,name='egon',args=(10,))
        # t1.daemon = True
        t1.setDaemon(True)
        t1.start()
    
        t2 = Thread(target=task,name='egon',args=(4,))
        t2.start()
    
        print('')

    七、线程互斥锁

    from threading import Thread,Lock
    # from multiprocessing import Lock
    import time
    import random
    
    money = 99
    
    
    def task(n,mutex):
        global money
        # 在修改数据的时候,枷锁
        mutex.acquire()
        temp = money
        time.sleep(0.1)
    
        money = temp - 1
        # 修改完以后,释放锁,其它线程就能再次抢到锁
        mutex.release()
    
    
    if __name__ == '__main__':
        ll=[]
        mutex=Lock()
        for i in range(10):
            t = Thread(target=task, args=(i,mutex))
            t.start()
            ll.append(t)
    
        for i in ll:
            i.join()
    
        print(money)

    八、GIL全局解释器锁理论

    1 python的解释器有很多,cpython,jpython,pypy(python写的解释器)
    2 python的库多,库都是基于cpython写起来的,其他解释器没有那么多的库
    3 cpython中有一个全局大锁,每条线程要执行,必须获取到这个锁
    4 为什么会有这个锁呢?python的垃圾回收机制
    5 python的多线程其实就是单线程
    6 某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行

    7 总结:cpython解释器中有一个全局锁(GIL),线程必须获取到GIL才能执行,我们开的多线程,不管有几个cpu,同一时刻,只有一个线程在执行(python的多线程,不能利用多核优势)

    8 如果是io密集型操作:开多线程
    9如果是计算密集型:开多进程
    (8 9 这两句话,只针对与cpython解释器)

    九、

    ---38---

  • 相关阅读:
    javascript 中数字计算精度缺失问题
    javascript闭包
    MySQL数据库的创建
    原生项目使用 sass
    git工具命令
    如何将你的node服务放到线上服务器
    Cookie、Session、Token 的区别
    东北师大-构建之法-2020秋最终成绩(并非期末成绩)
    20201220-东北师范大学-助教-周总结-第14次
    东北师范大学-构建之法-20201207作业成绩
  • 原文地址:https://www.cnblogs.com/guojieying/p/13562130.html
Copyright © 2020-2023  润新知