python进程池及进程锁


前言

提示:以下是本篇文章正文内容,下面案例可供参考

一、进程锁

进程之间,运行程序的时候多进程中,进程之间应避免进行通信,如果要进行通信就要用比较安全的工具,比如进程锁来解决此类问题(实现数据共享),实际中,可能大多使用数据库来解决进程和进程之间处理数据共享的问题。
进程之间的数据是相对独立的

实例

import time,os,random
from multiprocessing import Process,Manager,Lock


def work(d,lock):
    with lock:
        d['count'] -=1


def main():
    lock = Lock()#进程锁
    with Manager() as m:
        dic = m.dict({'count':100})
        p_list = []
        for i in range(98):
            p = Process(target=work,args=(dic,lock,))
            p_list.append(p)
            p.start()
        for p in p_list:
            p.join()
        print(dic)


    pass

if __name__=='__main__':
    main()

运行结果为:

{'count': 2}

Process finished with exit code 0

在python程序运行时将某一个进程锁住。那么这个进程知道里面的任务执行完毕主动释放后才会解锁让下一个任务去使用这个进程,进程锁就像是保护进程任务的一个工具一样。

二、进程池

比如你有成千上万个任务要去执行,并不是直接创建成千上万的进程!!
创建进程、销毁进程——不能无限制的根据任务去开启进程做事。。。。
池子——固定数量的进程。

有事情了,从进程池里拿一个进程出来做事,做完事,不关闭进程!放回池子里继续等待下一个任务。

示例一(进程池)

import time,os,random
from multiprocessing import Pool


def func(n):
    for i in range(10):#把1-100每个数字打印10次
        print(n+1)

def main():
    start = time.time()
    pool = Pool(5)  #池子里五个进程
    pool.map(func,range(100))#定义一百个任务
    t2 = (time.time()-start)
    print(t2)


共消耗时间:

0.13670897483825684

示例二(多进程)

import time,os,random
from multiprocessing import Pool,Process


def func(n):
    for i in range(10):#把1-100每个数字打印10次
        print(n+1)

def main():
    start = time.time()
    '''
    pool = Pool(5)  #池子里五个进程
    pool.map(func,range(100))#定义一百个任务
    '''
    p_list = []
    for i in range(100):
        p = Process(target=func,args=(i,))
        p_list.append(p)
        p.start()
    for p in p_list:
        p.join()
    t2 = (time.time()-start)
    print(t2)





    pass

if __name__=='__main__':
    main()


共消耗时间:

1.9545559883117676

进程池同步和异步的调用👇

​ 同步调用:在发出一个任务时,自任务开始运行直到结束(可能遇到IO),只有返回一个返回值之后,才会发出下一个任务。

​ 异步调用:一次发布多个任务,然后就直接执行下一行代码。不用等待结束。
shutdown:

1.让主进程等待进程池中所有的子进程都结束后,再执行。
2. 在上一个进程池没有完成所有的任务之前,不允许添加新任务。
一个任务是通过一个函数实现的,任务完成了,它的返回值就是函数的返回值。

实例(同步调用)——拿到结果为止。。。。

import time,os,random
from multiprocessing import Pool,Process


#同步调用
def work(n):
    print("%s running"%(os.getpid()))
    time.sleep(2)
    return n**2


def main():
    p = Pool(3)
    res_l = []
    for i in range(10):
        res = p.apply(work,args=(i,))#同步调用,直到拿到结果为止,不管任务是否阻塞,同步调用都会在原地等着。
        res_l.append(res)
    print(res_l)




    pass

if __name__=='__main__':
    main()

运行结果为:

3964 running
11388 running
12504 running
3964 running
11388 running
12504 running
3964 running
11388 running
12504 running
3964 running
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Process finished with exit code 0

实例(异步调用)

import time,os,random
from multiprocessing import Pool,Process


#同步调用
def work(n):
    print("%s running"%(os.getpid()))
    time.sleep(2)
    return n**2


def main():
    p = Pool(3)
    res_l = []
    for i in range(10):
        res = p.apply_async(work,args=(i,))#异步调用,三个进程不会同时开启同时结束
        res_l.append(res)
    p.close()
    p.join()#异步提交任务,主进程需要join,等待进程池里的任务都处理完后,可以用get去搜集结果。
    #如果不用join,主进程结束,进程池还没来的及执行,跟着结束
    print(res_l)#但是打印出来的是对象
    for r in res_l:
        #需要使用get去获取apply_async的结果,因为apply没有get方法
        print(r.get())




    pass

if __name__=='__main__':
    main()

运行结果为:

17832 running
17560 running
20460 running
17832 running
17560 running
20460 running
17832 running
20460 running
17560 running
17832 running
[<multiprocessing.pool.ApplyResult object at 0x0000018665A33FC8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A600C8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60188>, <multiprocessing.pool.ApplyResult object at 0x0000018665A602C8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60408>, <multiprocessing.pool.ApplyResult object at 0x0000018665A605C8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60708>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60848>, <multiprocessing.pool.ApplyResult object at 0x0000018665A609C8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60588>]
0
1
4
9
16
25
36
49
64
81

Process finished with exit code 0

三、简易进程池聊天程序

首先要查看一下默认pool进程数是cpu的核心数量(os.cpu_count())
查看我本机的cpu核心数量👇

import time,os,random
from multiprocessing import Pool,Process




def main():
    a = os.cpu_count()
    print(a)

    pass

if __name__=='__main__':
    main()

运行结果为:

8

在这里插入图片描述
server.py服务端程序如下:

#! /usr/bin/python
# -*- coding:UTF-8 -*-

from socket import *
import os
from multiprocessing import Pool

#服务端程序
server = socket(AF_INET,SOCK_STREAM)
#当socket被关闭之后,立刻重新使用端口,配合使用异步通信
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server.bind(('127.0.0.1',8080))
server.listen(5)

def talk(conn,addr):
    print("进程%s 用户%s"%(os.getpid(),addr))
    while True:
        try:
            msg = conn.recv(1024)
            if not msg:break
            conn.send(msg.upper())
        except Exception:
            break

def main():
    p = Pool(4)#进程池里只开四个进程
    while True:
        conn,addr = server.accept()
        p.apply_async(talk,args=(conn,addr,))



    pass

if __name__ == '__main__':
    main()

client.py客户端程序如下:

#! /usr/bin/python
# -*- coding:UTF-8 -*-

from socket import *
#客户端程序

client = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))

def main():
    while True:
        msg = input(">> ").strip()
        if not msg:continue
        client.send(msg.encode("utf-8"))
        msg = client.recv(1024)
        print(msg.decode("utf-8"))

    pass

if __name__ == '__main__':
    main()

分别运行起来后:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
多开几个cmd运行也是可以的
ps:这个程序实现的最多就是四个client......第五个以后的需要排队等待前面四个有一个退出才能连上通信
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值