多进程编程(一)

多进程编程--模块multiprocessing

import multiprocessing  #引入多进程编程模块

进程的生命周期:

1、创建进程---multiprocessing.Process()#参数 group=None【windows中可忽略,linux、unix中使用用户分组】,target=None【进程要做的事情,通常为函数名】,name=None【进程名称,可自定义】,args=()【数组参数】,kwargs={}【字典参数】

2、启动进程--start()

3、判断进程状态--is_alive()

4、主进程等待--join()

5、进程的返回值--exitcode()

6、结束进程  --terminate()#不推荐使用

多进程编程例1:

import multiprocessing  

def func(msg):
    time.sleep(2)
    return msg

if __name__ == '__main__':
    p1= multiprocessing.Process(target=func,name='he',args=('hello,word',))#创建进程
    print(p1.is_alive())#判断进程的存活状态
    p1.start()          #启动进程
    print(p1.is_alive())
    p1.join()           #主进程等待
    print(p1.exitcode)  #获取进程的返回值
    print(p1._name)

多进程编程例2:

import multiprocessing
import urllib2
def func1(url):
    response = urllib2.urlopen(url)
    html = response.read()
    print(html[1:20],'------func1')
    time.sleep(2)

def func2(url):
    response = urllib2.urlopen(url)
    html = response.read()
    print(html[1:20],'------func2')
    time.sleep(2)


if __name__ == '__main__':
    p1=multiprocessing.Process(target=func1,args=('http://www.baidu.com',))
    p2=multiprocessing.Process(target=func2,args=('http://www.sogou.com',))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print('done')

练习1:

写一个多进程,程序针对全局变量count,默认值是0,完成加10的操作。采用10个进程并发操作,最后统一join,之后打印出全局变量count的值。

count = 0
def func1(num=10):
    global count
    count +=num
    print('------',count,'------')
    return count

if __name__ == '__main__':
    ap = []
    for i in range(10):
        p = multiprocessing.Process(target= func1)
        ap.append(p)
    for i in ap:
        i.start()
    for i in ap:
        i.join()
    print('done')
    print(count)
#执行结果

('------', 10, '------')
('------', 10, '------')
('------', 10, '------')
('------', 10, '------')
('------', 10, '------')
('------', 10, '------')
('------', 10, '------')
('------', 10, '------')
('------', 10, '------')
('------', 10, '------')
done
0#count

练习2:解释为何count的值还是0。

进程占用的内存空间:1、文本区域2、数据区域3、堆栈空间。对于当前py主进程来讲count为全局变量,在创建10个子进程时,复制了10个(文本区域、数据区域)内存占用。由于进程间相互独立,每个进程都有自己的全局变量count,每个加10操作都是针对自己的count值操作,没有操作到主进程的count。及子进程的count为10,主进程的count为0.

练习3:进程间共享变量

import multiprocessing

def f(n,a):
    n=3.14
    for i in range(len(a)):
        a[i] = -a[i]

if __name__ =='__main__':
    num = 0
    arr = range(10)
    p = multiprocessing.Process(target=f,args=(num,arr))
    p.start()
    p.join()
    print(p.exitcode)
    print(num)
    print(arr[:])

#执行结果

0
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

进程间共享数据

1、Value--单个变量(浮点型:Value('d',1.0)\整数型:Value(‘i’,2)\字符串型:Value(c_char_p,'hello'))【共享内存】

2、Array --数组列表 【共享内存】

3、Manager  【共享进程】

例1

def f(n,a):
    n.value=3.14
    for i in range(len(a)):
        a[i] = -a[i]

if __name__ =='__main__':
    num = multiprocessing.Value('d',1.0) #Value的参数类型,数组参数、字典参数
    arr = multiprocessing.Array('i',range(10))#Arr的元素类型,数组参数、字典参数
    p1 = multiprocessing.Process(target=f,args=(num,arr)) #arr和value在进程间可以共享,共享内存的方式
    p1.start()
    p1.join()
    # print(p1.exitcode)
    print(num)
    print(num.value)
    print(arr[:])
    # 执行结果
    # <Synchronized wrapper for c_double(3.14)>
    # 3.14
    # [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
    p2 = multiprocessing.Process(target=f,args=(num,arr))
    p2.start()
    p2.join()
    # print(p.exitcode)
    print(num)
    print(num.value)
    print(arr[:])
    # 执行结果
    # <Synchronized wrapper for c_double(3.14)>
    # 3.14
    # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
#     进程1和进程2操作的是同一组数据

练习:把count变量封装成Count类,实现增1方法increment及getValue的方法。

class Count:
    def __init__(self,count=0):
        self.__count=count

    def increment(self):
        self.__count+=1

    def getVlaue(self):
        return self.__count


if __name__ =='__main__':
    c=Count()
    for i in range(10):
        c.increment()
    print(c.getVlaue())

练习:把类Count中的属性count,使用Value表示,并且使用多进程进行count的自增操作,50个进程进行操作。

写法一:

import multiprocessing
class Count:
    def __init__(self,count=0):
        self.__count=count

    def increment(self):
        self.__count+=1

    def getVlaue(self):
        return self.__count

if __name__ =='__main__':
    c=Count()
    num = multiprocessing.Value('i',c.getVlaue())
    procs =[multiprocessing.Process(target=c.increment(),args=(num,)) for i in range(50)]
    for i in procs:
        i.start()
    for i in procs:
        i.join()
    print(c.getVlaue())

写法二

from multiprocessing import Process,Value
import time
class Count:
    def __init__(self,count):
        self.__count=Value('i',count)

    def increment(self):
        self.__count.value+=1

    def getVlaue(self):
        return self.__count.value

def func(counter):
    time.sleep(0.5)#等待时间
    counter.increment()

if __name__ =='__main__':
    c=Count(0)
    procs =[Process(target=func,args=(c,)) for i in range(100)]
    for i in procs:
        i.start()
    for i in procs:
        i.join()
    print(c.getVlaue())

疑问:为什么加上等待时间0.5后,实际执行的进程数比预期要少;sleep的时间越长,出错概率高,并发进程数越多,出错的概率越高?

共享内存,多个进程同时可以对同一个内存进行写操作。先读后写,导致某一个进程读到时,加一加到7,刚好此时有另外一个进程也写到+1也加到7。

 

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

测试有头发

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值