• Python 进程和线程


    对于OS来说,一个任务(如打开word)就是一个进程

    有些进程不止同时干一件事,如word可以同时进行打字、拼写检查、打印等事情,进程内的子任务称为线程

    多进程

    multiprocessing模块  跨平台版本的多进程模块

    启动一个子进程并等待其结束

     1 #!/usr/bin/python3
     2 
     3 from multiprocessing import Process
     4 import os
     5 
     6 #子进程要执行的代码
     7 def run_proc(name):
     8     print('运行的子进程 %s(%s)' % (name, os.getpid()))
     9     
    10 if __name__ == '__main__':
    11     print('父进程 %s' % os.getpid())
    12     p = Process(target = run_proc, args = ('qwer',))  #创建子进程对象
    13     print('子进程将要开始运行--------')
    14     p.start()
    15     p.join()  #等待子进程结束后再继续往下运行,通常用于进程间的同步
    16     print('子进程结束---------')

    子进程只需要调用getpid()就可拿到父进程ID

    Pool    启动大量的子进程  用进程池的方式

     1 #!/usr/bin/python3
     2 
     3 from multiprocessing import Pool
     4 import os,time,random
     5 
     6 def long_time_task(name):
     7     print('Run task %s (%s)-----' % (name, os.getpid()))
     8     start = time.time() #放回当前时间戳
     9     time.sleep(random.random()*3)
    10     end = time.time()
    11     print('Task %s runs %0.2fs' % (name, (end-start)))
    12 
    13 if __name__ == '__main__':
    14     print('父进程 %s' % os.getpid())
    15     p = Pool(4)  #设置同时跑四个进程
    16     for i in range(5):
    17         p.apply_async(long_time_task, args = (i,))  #apply应用程序  asvnc异步化
    18     print('等待所有子程序完成------')
    19     p.close()
    20     p.join()  
    21     print('所有子程序完成')

    调用join()之前必须先调用close()

    进程间通信

    Process之间肯定是需要通信的,Python的multiprocessing模块包装了底层的机制,提供了QueuePipes等多种方式来交换数据。

    Queue为例,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读数据:

     1 #!/usr/bin/python3
     2 
     3 from multiprocessing import Process,Queue
     4 import os,time,random
     5 
     6 #写数据
     7 def write(q):
     8     print('写进程: %s' % os.getpid())
     9     for value in ['A', 'B', 'C']:    
    10         print('Put %s to queue------' % value)
    11         q.put(value)
    12         time.sleep(random.random())
    13         
    14 #读数据
    15 def read(q):
    16     print('读进程: %s' % os.getpid())
    17     while True:
    18         value = q.get(True)
    19         print('Get %s from queue------' % value)
    20         
    21 if __name__ == '__main__':
    22     #父进程创建Queue,并传给各个子进程
    23     q = Queue()
    24     pw = Process(target = write, args = (q,))
    25     pr = Process(target = read, args = (q,))
    26     #启动子进程pw,写入
    27     pw.start()
    28     #启动子进程pr,读取
    29     pr.start()
    30     #等待pw结束
    31     pw.join()
    32     #pr进程死循环,无法等待其结束,强行终止
    33     pr.terminate()

    多线程

    启动一个线程就是把一个函数传入并创建Thread(实例),然后start()执行

     1 #!/usr/bin/python3
     2 
     3 import time,threading
     4 
     5 #线程要执行的代码
     6 def loop():
     7     print('Thread %s is runing----' % threading.current_thread().name)
     8     n = 0
     9     while n<5:
    10         n = n+1
    11         print('thread %s>>>%s' % (threading.current_thread().name, n))
    12         time.sleep(1)
    13     print('thread %s end' % threading.current_thread().name)
    14     
    15 print('thread %s is runing----' % threading.current_thread().name)
    16 t = threading.Thread(target = loop, name = 'LoopThread')
    17 t.start()
    18 t.join()
    19 print('thread %s end' % threading.current_thread().name)

    任何进程默认会启动一个线程(主线程),主线程又可以启动新的线程,current_thread()函数返回当前线程的实例,如果不给子线程指定名字,默认Thread-1,Thread-2........

    Lock

    多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响

    多线程中,所有变量都由所有线程共享,为防止修改冲突,需给线程上锁,锁只有一个,同一个时刻最多只有一个线程持有该锁

     1 #!/usr/bin/python3
     2 
     3 import time,threading
     4 
     5 balance = 0  #假定这是银行存款
     6 
     7 def change_it(n):  #先存后取,结果应该为0
     8     global balance
     9     balance = balance + n
    10     balance = balance - n
    11 
    12 lock = threading.Lock()  #创建锁对象
    13 
    14 def run_thread(n):
    15     for i in range(100000):
    16         lock.acquire()   #上锁
    17         try:
    18             change_it(n)
    19         finally:  #改完一定要释放锁
    20             lock.release()
    21         
    22 t1 = threading.Thread(target = run_thread, args = (5,))
    23 t2 = threading.Thread(target = run_thread, args = (10,))
    24 t1.start()
    25 t2.start()
    26 t1.join()
    27 t2.join()
    28 print(balance)

    没上锁时,数据冲突

    上锁后

  • 相关阅读:
    使用 Terraform 在阿里云上快速部署 MQTT 集群
    Neuron Newsletter 202206|新增 1 个南向驱动、开源前端代码
    EMQX Cloud 更新:日志分析增加更多参数,监控运维更省心
    os:systemctl文档(四)systemd.unit
    教育:中国孩子缺失的教育
    os:apt sources.list文件说明
    asm:80x86寄存器详解(转载)
    asm:gdb资源集合(linux)
    asm: gdb 文档(gdb调试工具)
    书法:书法的理解
  • 原文地址:https://www.cnblogs.com/bfcs/p/10783045.html
Copyright © 2020-2023  润新知