• Python中的进程和线程


    一、Python中两种创建进程的方式

    1、os.fork只适用于Linux/Mac
    2、使用multiprocessing模块可以跨平台实现多进程

    使用os.fork(),像Linux平台上那样创建多进程。

    # multiprocessing.py
    import os
    
    print 'Process (%s) start...' % os.getpid()
    pid = os.fork()
    if pid==0:
        print 'I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())
    else:
        print 'I (%s) just created a child process (%s).' % (os.getpid(), pid)
    

    关于fork需要知道以下几点:fork之后程序相当于分叉了,fork会返回两次,每次的返回值都为int。如果此值为0,表示当前进程为父进程,如果此值不为0表示当前进程为子进程且此值代表子进程的id。

    使用multiprocessing
    进程之间是不共享数据的,它们不共享内存,所以创建进程比较耗费资源。进程之间通信需要类似管道的机制。

    from multiprocessing import Process
    import time
    
    x = 100
    
    
    def f():
        while 1:
            time.sleep(2)
            print(x)#这里会一直输出100
    
    
    if __name__ == '__main__':#必须在main中才可以创建进程
        x=2
        p = Process(target=f)
        p.start()
        time.sleep(7)
        x=3
        time.sleep(3)
        print("over")
        print(x)
    

    二、编程上的一些用法

    主要是两个模块:multiprocessing和threading

    1、获取当前线程名称

    multiprocessing.current_process().name
    threading.current_thread().name
    

    2、多线程编程时,默认情况下,主线程结束之后,等待全部子线程执行完毕才会退出

    import threading
    import time
    
    def run():
        time.sleep(2)
        print('当前线程的名字是: ', threading.current_thread().name)
        time.sleep(2)
    
    
    if __name__ == '__main__':
    
        start_time = time.time()
    
        print('这是主线程:', threading.current_thread().name)
        thread_list = []
        for i in range(5):
            t = threading.Thread(target=run)
            thread_list.append(t)
    
        for t in thread_list:
            t.start()
    
        print('主线程结束!' , threading.current_thread().name)
        print('一共用时:', time.time()-start_time)
    

    3、将子线程设置为deamon类型,则主线程不必等待子线程结束

    import threading
    import time
    
    def run():
    
        time.sleep(2)
        print('当前线程的名字是: ', threading.current_thread().name)
        time.sleep(2)
    
    
    if __name__ == '__main__':
    
        start_time = time.time()
    
        print('这是主线程:', threading.current_thread().name)
        thread_list = []
        for i in range(5):
            t = threading.Thread(target=run)
            thread_list.append(t)
    
        for t in thread_list:
            t.setDaemon(True)
            t.start()
    
        print('主线程结束了!' , threading.current_thread().name)
        print('一共用时:', time.time()-start_time)
    

    4、在主线程中,使用子线程.join()来等待子线程运行结束

    join()会将一切权力交给子线程,主线程会阻塞直到子线程结束。

    import threading
    import time
    
    def run():
    
        time.sleep(2)
        print('当前线程的名字是: ', threading.current_thread().name)
        time.sleep(2)
    
    
    if __name__ == '__main__':
    
        start_time = time.time()
    
        print('这是主线程:', threading.current_thread().name)
        thread_list = []
        for i in range(5):
            t = threading.Thread(target=run)
            thread_list.append(t)
    
        for t in thread_list:
            t.setDaemon(True)
            t.start()
    
        for t in thread_list:
            t.join()
    
        print('主线程结束了!' , threading.current_thread().name)
        print('一共用时:', time.time()-start_time)
    

    三、进程和线程的区别和联系

    • 进程是重量级的,需要占用较多资源。线程是轻量级的。
    • 一个进程可以包括多个线程,但是一个进程只有一个主线程。操作系统的全部进程组成一棵树,父进程的死亡会导致子进程的终止。
    • 同一进程的多个线程之间是共享数据的,不同进程之间数据相互独立(进程之间交流比较困难)。
    • 尽量使用线程。

    Chrome里面每一个tab页都是一个独立的进程,可以打开任务管理器查看一下。
    Tomcat中每一次请求都会开辟一个线程,Java强大的异常机制把错误牢牢地抓住了,不然一个线程一崩整个网站就崩了(因为整个tomcat程序就是一个进程,进程中的子线程崩了其它子线程也要受牵连,整个进程就崩了)。

    四、为什么说Python中的线程有点鸡肋

    不同线程同时访问资源时,需要使用保护机制,Python中使用GIL(解释器全局锁)。直观上,这是一个加在解释器上的全局(从解释器的角度看)锁。这意味着对于任何Python程序,不管有多少的处理器,任何时候都总是只有一个线程在执行。所以,如果没有IO操作,python中的多线程比单线程效率还低。

    在任意时间只有一个Python解释器在解释Python bytecode。
    如果你的代码是CPU密集型,多个线程的代码很有可能是线性执行的。所以这种情况下多线程是鸡肋,效率可能还不如单线程因为线程切换白费事。
    但是,如果你的代码是IO密集型,多线程可以明显提高效率。例如制作爬虫,绝大多数时间爬虫是在等待socket返回数据。这个时候C代码里是有release GIL的,最终结果是某个线程等待IO的时候其他线程可以继续执行。

    参考资料

    关于Python多线程、多进程,看完廖雪峰的教程就足够了。
    廖雪峰Python教程

  • 相关阅读:
    java常用IO流集合用法模板
    java根据概率生成数字
    从浏览器直接转跳到APP具体页面---(魔窗)MagicWindow使用教程
    java开源即时通讯软件服务端openfire源码构建
    还在繁琐的敲MVP接口和实现类吗,教你一秒搞定。
    手把手带你走进MVP +Dagger2 + DataBinding+ Rxjava+Retrofit 的世界
    poj3666(DP+离散化)
    poj3616(LIS简单变式)
    hdoj2859(矩阵DP)
    poj1088(记忆化搜索入门题)
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/7845570.html
Copyright © 2020-2023  润新知