zoukankan      html  css  js  c++  java
  • 进程

    什么是进程?

      进程,是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。前面的话我也没懂,用非官方的白话来解释就是——执行中的程序是进程,比如qq不是进程,但是当我们双击qq开始使用它的时候,它就变成了一个进程。我们写的python程序,只有当我们执行它的时候,它才是进程。我们正在执行的IE浏览器,QQ,pycharm都是进程,从操作系统的角度来讲,每一个进程都有它自己的内存空间,进程之间的内存是独立的。

      举个例子:进程就像是工厂中的一个车间,在计算机中这个车间就是一块内存空间,车间中有很多工人,每一个工人就相当于一个线程,车间中的资源对于多有的工人来讲都是共享的(内存共享)。

    牛刀小试,写一个多进程的程序

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import time
    from multiprocessing import Process     
    
    def run(i):
        time.sleep(5)
        print i
    
    if __name__ == "__main__":
      for i in range(10):
        i = Process(target=run,args=(i,))
        i.start()

    执行结果:

          
    join()方法
      join
    ()方法会阻塞程序,只有当一个进程执行完了之后才会执行下一个进程,使得多进程失去了并发执行的意义。
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import time
    from multiprocessing import Process
    
    def run(i):
        time.sleep(5)
        print i
    
    if __name__ == "__main__":
      for i in range(10):
        i = Process(target=run,args=(i,))
        i.start()
        i.join()        #会阻塞程序

    执行结果


    那么问题来了,join()存在的意义是什么呢?
      应用场景:当我们起了多个进程帮我们完成了一些任务之后,提示我们这些任务完成了,应该怎么做?
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import time
    from multiprocessing import Process
    
    def run():
        time.sleep(3)
        print "执行任务中..." 
    
    if __name__ == "__main__":
      for i in range(3):
        i = Process(target=run,args=())
        i.start()
    print "任务执行完了..."

    执行结果:



    结果并不是我们想要的....

    这个时候join()方法就派上用场了

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import time
    from multiprocessing import Process

    
    

    def run():
    time.sleep(3)
    print "执行任务中..."

    
    

    if __name__ == "__main__":
    for i in range(3):
    i = Process(target=run,args=())
    i.start()
    i.join()
    print "任务执行完了..."

    执行结果:

    顺序对了,但是没有并发呀.....

     ok,了解到join()方法用到哪里之后,我们再来解决并发的问题

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import time
    from multiprocessing import Process
    
    def run():
        print "执行任务中..."
        time.sleep(3)
    
    if __name__ == "__main__":
      plist = []
      for i in range(3):
        i = Process(target=run,args=())
        plist.append(i)
      for j in plist:
        j.start()
      for k in plist:
        j.join()
    print "任务执行完了..."
    
    执行结果:

     有一条流水线横跨了两个车间

      不同的进程都有自己独立的内存块,相互之间是不能访问的。但是有一条牛逼的流水线需要多个车间协同完成,即在计算机中有一个任务需要多个进程协同完成,那如何让进程间进行数据共享呢?

    #!/usr/bin/env python
    #coding:utf-8
    
    from multiprocessing import Process
    from multiprocessing import Manager
    
    import time
    
    li = []
    
    def foo(i):
        li.append(i)
        print 'say hi',li
    
    for i in range(10):
        p = Process(target=foo,args=(i,))
        p.start()
         
    print 'ending',li
    进程间不能数据共享
    #方法一,Array
    from multiprocessing import Process,Array
    temp = Array('i', [11,22,33,44])
     
    def Foo(i):
        temp[i] = 100+i
        for item in temp:
            print i,'----->',item
     
    for i in range(2):
        p = Process(target=Foo,args=(i,))
        p.start()
     
    #方法二:manage.dict()共享数据
    from multiprocessing import Process,Manager
     
    manage = Manager()
    dic = manage.dict()
     
    def Foo(i):
        dic[i] = 100+i
        print dic.values()
     
    for i in range(2):
        p = Process(target=Foo,args=(i,))
        p.start()
        p.join()
    特殊的数据结构实现数据共享

    multiprocessing模块中提供的数据结构是进程安全的的:虽然对个进程都可以对它进行操作,但是在同一时刻只有一个进程在进行读写数据,所以不会造成脏数据。ok,这是multiprocessing模块提供的这些数据结构本身的特性,但是普通的操作,比如多个进程同时修改MySQL中的某一个数据,是不是就会造成脏数据,那怎么办?----> 进程锁来了....

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    from multiprocessing import Process, Array, RLock
    
    当创建进程时(非使用时),共享数据会被拿到子进程中,当进程中执行完毕后,再赋值给原值。
    def Foo(lock,temp,i):
        """
        将第0个数加100
        """
        lock.acquire()
        temp[0] = 100+i
        for item in temp:
            print i,'----->',item
        lock.release()
    
    lock = RLock()
    temp = Array('i', [11, 22, 33, 44])
    
    for i in range(20):
        p = Process(target=Foo,args=(lock,temp,i,))
        p.start()

    注意:

      线程锁有两种:RLOCK和LOCK
                 Rlock在一个线程中可以被多次调用,lock只能被调用一次,如果调用多次就会造成死锁,使用rlock 的时候acquire和release必须成对出现否则就会造成线程的死锁。
     提高程序执行效率---->进程池:
        为了提高程序的效率才有进程池,当有任务需要起进程的时候可以直接从进程池中拿一个已经存在的进程,进程池中的进程并没有去执行具体的任务,只是在进场池中待着,ps -ef查看系统进程的时候可以看到进程的数量是进场池中的数量,而不是具体在执行任务的进程的数量,为什么这样会提高进程的执行效率呢?当我们使用ssh连接远端主机传输比较小的文件的时候,花费时间的是连接的过程,而不是传输文件的过程。类比到进程池,起进程的这个过程往往会耗费一定的时间,进程池就是直接帮我们起好一定数量的进程,随用随取。
    from multiprocessing import Pool
    import time
    
    def r(i):
        time.sleep(10)
        print i
    
    pool = Pool(15)   #起15个进程,当不指定参数的时候,默认会起和cpu核数一样的进程数
    
    for i in range(19):
         pool.apply(r,(i,))   #apply方法会顺序执行,不是并发的
         pool.apply_async(r,(i,))    #是异步执行的,是并发的
    pool.close()   #关闭进场池,进场池中的进程不在接收任务了
    pool.join()    #主进程等待子进程执行完了之后再退出

    pool.terminate() #该方法和join()方法相反,当程序执行到这里的时候就会直接退出,而不会管子进程有没有执行完。
    print "end..."

     多进程的时候获取进程的执行结果

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    from multiprocessing import Pool
    import time
    
    def run(i):
        print i
        return i
    
    pool = Pool()
    result = []
    for i in range(5):
         r = pool.apply_async(run,(i,))
         result.append(r)
    pool.close()
    pool.join()
    print "----------------------------"
    for i in result:
        print i.get()
    print "end..."
    方法一
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    from multiprocessing import Pool
    import time
    
    def run(i):
        print i
        return i
    
    global relist
    relist = []
    
    def last(i):
        relist.append(i)
    
    pool = Pool()
    result = []
    for i in range(5):
         pool.apply_async(run,(i,),callback=last)
    pool.close()
    pool.join()
    print "----------------------------"
    print relist
    方法二
  • 相关阅读:
    Qt/Qml 电子书阅读器
    Qt/Qml 翻页特效
    vue如何引入本地js(不被打包编译的js)文件
    CSS3解决移动端手指点击或滑动屏幕时出现的浅蓝色背景框
    vue移动端touch插件
    vue组件间通信六种方式(完整版)
    Vue 过渡实现轮播图
    vue中遇到的坑 --- 变化检测问题(数组相关)
    Vue判断设备是移动端还是pc端
    vue项目如何监听窗口变化,达到页面自适应?
  • 原文地址:https://www.cnblogs.com/along1226/p/5646922.html
Copyright © 2011-2022 走看看