Python之进程

什么是进程

  程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。在多道编程中,咱们容许多个程序同时加载到内存中,在操做系统的调度下,能够实现并发地执行。这是这样的设计,大大提升了CPU的利用率。进程的出现让每一个用户感受到本身独享CPU,所以,进程就是为了在CPU上实现多道编程而提出的。编程

多道程序设计技术

  所谓多道程序设计技术,就是指容许多个程序同时进入内存并运行。即同时把多个程序放入内存,并容许它们交替在CPU中运行,它们共享系统中的各类硬、软件资源。当一道程序因I/O请求而暂停运行时,CPU便当即转去运行另外一道程序。多线程

多进程

实例(能够循环生成多个子进程)并发

from multiprocessing import Process

def f(name):
    print('hello', name)
 
if __name__ == '__main__':
    p = Process(target=f, args=('bob',))  #生成一个子进程
    p.start()                  #启动一个子进程   
    p.join()                  #等待子进程的执行结束

多进程间的通信

  因为多进程与多线程不一样,多线程是处在同一个进程之间,因此多线程之间的内存是共享的,他们能够修改同一个内存中的数据,能够相互之间达到内存共享。可是多进程则不一样,多进程之间因为内存独立,因此数据之间不能直接共享,那么咱们如何实现多进程之间的通信呢?app

1、Queue队列

from multiprocessing import Queue,Process

def func(a):
    print('这是子进程:',a.get())

if __name__ == '__main__':
    q = Queue()
    q.put(123)
    p = Process(target=func,args=(q,))
    p.start()

运行结果:
>>这是子进程: 123

  进程Queue和线程queue的使用方法基本一致,可是咱们在父进程中放入Queue中的数据能够在子进程中拿出(反之也能够),这种方法实现了进程间的数据传递。异步

2、Pipes管道

from multiprocessing import Process,Pipe
def func(n):
    print(n.recv())
    n.send('from son')

if __name__ == '__main__':
    f,s = Pipe()
    p = Process(target=func,args=(s,))
    p.start()
    f.send('from father')
    print(f.recv())

  实例化管道以后,会返回两个对象,也就是管道的两端,将一端留在父进程,一端做为参数传入给子进程,而后能够经过send和recv方法接收和发送数据,以达到不一样进程间的通讯。async

3、Managers

from multiprocessing import Process,Manager
import os

def func(a,b):
    a[os.getpid()] = os.getpid()
    b.append(os.getpid())

if __name__ == '__main__':
    manager = Manager()
    d = manager.dict()
    l = manager.list()
    l2 = []
    for i in range(10):
        p = Process(target=func,args=(d,l))
        p.start()
        l2.append(p)
    for i in l2:
        i.join()

# os.getpid()是得到当前进程的id,os.getppid()是得到当前父进程的id

  实例化manager以后。经过manager来生成字典,列表等等,将其传给子进程,经过这些数据格式来实现不一样进程间的通信。A manager returned by  Manager() will support types listdictNamespaceLockRLockSemaphoreBoundedSemaphoreConditionEventBarrierQueueValue and Arrayide

进程锁

from multiprocessing import Process, Lock
def f(l, i):
    l.acquire()
    print('hello world', i)
    l.release()
if __name__ == '__main__':
    lock = Lock()
    for num in range(10):
        Process(target=f, args=(lock, num)).start()
进程锁

  有人说,线程之间加锁是为了不数据混乱,进程之间内存都已经不共享了,为何还要加锁呢?若是多个进程同时占有对方须要的资源而同时请求对方的资源,而它们在获得请求以前不会释放所占有的资源,那么就会致使死锁的发生,也就是进程不能实现同步。举个例子就是竞争资源,如当系统中供多个进程共享的资源如打印机、公用队列等,其数目不足以知足进程的须要时,会引发诸进程的竞争而产生死锁。函数

进程池

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,若是进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。ui

进程池中的方法:spa

  • apply                        从进程池里取一个进程并同步执行     
  • apply_async             从进程池里取出一个进程并异步执行
  • terminate                       马上关闭进程池
  • join                                主进程等待全部子进程执行完毕,必须在close或terminete以后
  • close                             等待全部进程结束才关闭线程池
from  multiprocessing import Pool
import time,os

def Foo(i):
    time.sleep(2)
    print('进程:',os.getpid())
    return 'ok'               #return的值被回调函数接收

def Bar(arg):
    print('-->该子进程执行完毕:', arg,os.getpid())     #由执行结果能够发现回调函数由父进程执行而不禁子进程执行          

if __name__ == '__main__':
    print('父进程:',os.getpid())
    pool = Pool(5)
    for i in range(10):
        pool.apply_async(func=Foo, args=(i,), callback=Bar)          #程序异步执行,也就是并行,Bar为回调函数,能够没有
        # pool.apply(func=Foo, args=(i,))         #若是执行这种方法,程序会变成同步执行,也就是串行  
    pool.close()
    pool.join()        # 进程池中进程执行完毕后再关闭,若是注释,那么程序直接关闭。
父进程: 904
进程: 12232
-->exec done: ok 904
进程: 14396
-->exec done: ok 904
进程: 16736
-->exec done: ok 904
进程: 17276
-->exec done: ok 904
进程: 2908
-->exec done: ok 904
进程: 12232
-->exec done: ok 904
进程: 14396
-->exec done: ok 904
进程: 16736
-->exec done: ok 904
进程: 17276
-->exec done: ok 904
进程: 2908
-->exec done: ok 904
执行结果
相关文章
相关标签/搜索