day10-进程池的使用

一、概述

   本篇博客主要写进程锁,__name__ == "__main__"函数作用,以及进程池的使用。

二、进程同步

2.1、进程锁

说明:通过multiprocessing中的Lock模块来实现进程锁。

from multiprocessing import Process,Lock   #导入进程锁

def f(l,i):
    l.acquire()    #加锁
    try:
        print("hello word",i)
    finally:
        l.release()   #释放锁

if __name__ == "__main__":
    lock = Lock()     #定义锁
    for num in range(10):
        Process(target=f,args=(lock,num,)).start() #把锁传入进程中

1、这边不禁的有个疑问,就是进程中不是相互独立的吗?为啥还要加锁呐?

虽然每个进程都是独立运行的,但是问题来了,它们共享一块屏幕。这个锁存在的意义就是屏幕共享。如果也想抱着打印数据,而我想也想打印数据的情况,就有可能乱套了,然后通过这个锁来控制,去打印的时候,这个屏幕只有我独占,导致屏幕不会乱。

2、代码中的__name__ == "__main__"是干嘛用的?

它的作用是为了区分你是主动执行这个脚本还是从别的地方把它当做一个模块去调用。如果主动执行这个脚本,那么__name__ == "__main__" 以下的代码就会执行,如果其他模块导入的,则在其他模块中不执行__name__ == "__main__"以下的代码。这边一般在一个模块中测试用的,但是其他模块又不能执行这部分代码

三、进程池

进程池的作用:防止启动太多的进程把系统干趴下,才有了进程池的限制,比如说,你起了100个进程,会变慢,起一个进程相当于克隆一个父进程,父进程占1G内存空间,100个进程就占101G的内存,所以进程池就是在同一时间允许多个进程在cpu上运行。

3.1、apply

说明:这个说明是同步执行的,也就是串行执行的

from  multiprocessing import Pool  #导入进程池模块pool
import time,os

def Foo(i):
    time.sleep(2)
    print("in process",os.getpid())  #打印进程号
    return i+100

if __name__ == "__main__":
    pool = Pool(processes=5)   #设置进程池个数为5,也可以写成pool = Pool(5),允许进程池同时放入5个进程,并且这5个进程交给cpu去运行
    for i in range(10):
        pool.apply(func=Foo, args=(i,))   #同步执行挂起进程
    print('end')
    pool.close()
    pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。

注:这边的5个进程只是挂起了,并没有真正的去执行,但是执行的时候,只能执行这个5个进程。这个apply是同步的,也就是串行的,一般不用。

3.2、apply_async

说明:异步执行,也就是并行执行。

from  multiprocessing import Pool   #导入进程池模块
import time,os

def Foo(i):
    time.sleep(2)
    print("in process",os.getpid())
    return i+100

if __name__ == "__main__":
    pool = Pool(processes=5)   #定义进程池
    for i in range(10):
        pool.apply_async(func=Foo, args=(i,))   #采用异步的方式,加进程池
    print('end')
    pool.close()
    pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。

注:最后的pool.join()不能省略,不然的话,这个pool的进程池就直接关闭了, 它不会等待执行的结果的。

3.3、异步下的回调函数

说明:在计算机中,这个程序执行完毕之后,再回调过来执行这个Bar。

from  multiprocessing import Process,Pool
import time,os

def Foo(i):
    time.sleep(2)
    print("in process",os.getpid())  #打印子进程的进程号
    return i+100

def Bar(arg):
    print('-->exec done:',arg,os.getpid())   #打印进程号

if __name__ == "__main__":
    pool = Pool(processes=2)
    print("主进程",os.getpid())   #主进程的进程号
    for i in range(3):
        pool.apply_async(func=Foo, args=(i,),callback=Bar)   #执行回调函数callback=Bar
    print('end')
    pool.close()
    pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。

#输出
主进程 4296
end
in process 48604
in process 46280
-->exec done: 101 4296
-->exec done: 100 4296
in process 48604
-->exec done: 102 4296

 说明:

  1. 回调函数说明fun=Foo干不完就不执行bar函数,等Foo执行完就去执行Bar
  2. 这个回调函数是主进程去调用的,而不是每个子进程去调用的。

回调函数的用处:

  比如说你从各个机器上备份完毕,在回调函数中自动写一个脚本,说备份完毕。

回调函数是主进程调用的原因?

  如果是子进程去调用这个回调函数,有多少个子进程就有多少个连接,如果是主进程的话,只需要一次长连接就可以了,这个效率就高了。

 

转载于:https://www.cnblogs.com/zhangqigao/articles/7360063.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值