zoukankan      html  css  js  c++  java
  • threading模块,python下的多线程

    一、GIL全局解释器锁
    In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

    无论你启动多少个线程,Python解释器在同一时刻,都只允许一个线程在cpu上执行,Python启动一个线程是调用C语言的接口,让操作系统启动线程,所以所有的线程调度是操作系统在执行,而Python解释器在启动线程后只能等待操作系统返回结果。所以Python解释器为了防止同一时刻多个线程操作同一个数据,造成数据混乱,所以在cpython解释器中,加入了global interpreter lock。

    注意:Jpython、pypy等解释器都没有GIL

    二、Python中的多线程
    - python 中的多线程虽然不能并行,但是能达到高并发的效果。并不是一无用处
    2.1 threading模块
    import threading
    import time
     
    def run(i): #定义每个线程要运行的函数
     
        print("线程::%s  正在运行" %i)
     
        time.sleep(1)
     
    if __name__ == '__main__':
    
        #注意args参数必须为元组格式,如只有一个参数后面要加括号 
        t1 = threading.Thread(target= run, args=(1, )) #生成一个线程实例     参数还有name 线程名,daemon 是否守护线程 True
        t2 = threading.Thread(target= run, args=(2, )) #生成另一个线程实例
     
        t1.start() #启动线程
        t2.start() #启动另一个线程
     
        print(t1.getName()) #获取线程名
        print(t2.getName())
    
    2.2 Join及守护线程
    当你在启动一个线程之后,前面说过由于是调用系统创建,所以主进程就和创建的线程没有关系了。想象一下如果主进程的执行依赖于线程返回的结果,可是线程执行需要一定时间,当主进程 done 了,线程还没结束。 那就有问题了。所以这个时候 join 的左右就出来了,某个线程实例执行 join 方法,主进程会等到该线程执行完毕再从 join 后开始执行

    如:我们生产10个线程。主线程同时等待所以线程执行完毕

    def run(i):
        print('线程  {} 在运行'.format(i))
        time.sleep(1)
        if i%2:
            print('子线程done....')
    
    thread_list = []
    for i in range(10):
        t = threading.Thread(target= run, args(i, ))
        t.start()
        thread_list.append(t)
    
    for t in thread_list:
        t.join()
    
    print('main thread done....')
    
    #执行结果为
    线程  0 在运行
    线程  1 在运行
    线程  2 在运行
    线程  3 在运行
    线程  4 在运行
    线程  5 在运行
    线程  6 在运行
    线程  7 在运行
    线程  8 在运行
    线程  9 在运行
    子线程done....
    子线程done....
    子线程done....
    子线程done....
    子线程done....
    main thread done....
    
    #如果不使用join  的话 ,结果为...
    线程  0 在运行
    线程  1 在运行
    线程  2 在运行
    线程  3 在运行
    线程  4 在运行
    线程  5 在运行
    线程  6 在运行
    线程  7 在运行
    线程  8 在运行
    线程  9 在运行
    main thread done....
    子线程done....
    子线程done....
    子线程done....
    子线程done....
    子线程done....
    
    
    

    在这儿我们可以看到,就算没有加 join 主进程还是等待子线程全部执行结束后才结束,但是中间执行类容不会等待,这是因为Python 自动在程序结尾处自动添加了 join

    2.3 守护线程
    设想一个列子:一个奴隶主创建了很多奴隶,奴隶主就是主进程,奴隶们是子线程,奴隶主只需要告诉奴隶们命令,他们就会去工作。奴隶主在创建奴隶们的时候,就给他们心脏上安了一个东西,告诉他们,只要我死了,不管你们当时在干嘛,这个东西就会工作,立刻杀死你们。意思就是主进程一旦结束,所有被设置为守护进程的子线程全部结束

    而在threading 模块中,这个安装到奴隶(子线程,守护进程)的东西就是 daemon = True.

    有两种方式实现,一是实例化一个线程时:
    t = threading.Thread(target= fun, args= ( para , ), daemon= True)

    第二种为:必须在线程执行前设置,一旦start 后设置,就会报错

    def run(i):
        print('线程  {} 在运行'.format(i))
        time.sleep(1.5)
        print('子线程done....')
    
    
    for i in range(2):
        t = threading.Thread(target= run, args= (i, ))
        t.setDaemon(True)   #必须在线程执行前设置
        t.start()
    
    print('main thread done....')
    
    #运行结果为
    
    线程  0 在运行
    线程  1 在运行
    main thread done....
    
    

    从最后的运行结果中可以看到,主进程并没有等着子线程执行完,就结束了!这就是 非守护线程, 守护进程的关系

    线程锁(互斥锁)、递归锁 点击这儿

  • 相关阅读:
    JPA与Hibernate的关系
    EJB里的问题解答
    EJB与JPA的关系
    EJB的魅惑来源
    EJB简介
    MyEclipse如何恢复删掉的文件
    EasyUI的功能树之扁平化
    EasyUI的功能树之异步树
    Spring AOP的日志记录
    简单理解IoC与DI
  • 原文地址:https://www.cnblogs.com/shiqi17/p/9545391.html
Copyright © 2011-2022 走看看