zoukankan      html  css  js  c++  java
  • python进程

    1.什么是进程

    进程:正在进行的过程或者一个任务,是系统进行资源调度和分配的基本单元。进程是操作系统中最基本、最重要的概念。是多道程序系统出现后,为了刻画系统内部出现的动态情况,描述系统内部各道程序的活动规律引进的一个抽象的概念,所有多道程序设计操作系统都建立在进程的基础上。

    进程与程序的区别:程序仅仅是一堆代码,而进程表示程序的运行过程。同一个程序被运行多次表示开启了多个进程。

    2.进程的并行与并发

    • 并行:指多个进程同时执行,即在同一时间段上有多个进程在运行,实现并行前提是计算机为多核。
    • 并发:属于为并行,是在单核的条件下实现并发,多个进程交替运行。

                

     

    3.同步异步阻塞非阻塞

    • 同步:一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列。要么成功都成功,失败都失败,两个任务的状态可以保持一致。
    • 异步:不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠的任务序列。

    在程序运行的过程中,由于被操作系统的调度算法控制,程序会进入:就绪、运行和阻塞三个阶段

    就绪:当进程已经分配到除CPU外的所有必要资源,子要获得处理机就可以立即执行。

    执行/运行:程序获得处理机,其程序正在运行。

    阻塞:正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起阻塞原因包括(等待I/O完成、申请缓冲不能满足、等待信号等)。

    4.进程的创建方式

    Python中创建进程主要应用Process类:

    Process(group , target , name , args , kwargs),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动) 强调:

    • 参数介绍:
    • group参数未使用,值始终为None
    • target表示调用对象,即子进程要执行的任务
    • args表示调用对象的位置参数元组,args=(1,2,'kkk',)
    • kwargs表示调用对象的字典,kwargs={'name':'kkk','age':18}
    • name为子进程的名称

    创建进程的两种方式:

    #开启进程方式一
    from multiprocessing import Process
    import time
    
    def test(name):
        print('%s is running' %name)
        time.sleep(3)
        print('%s is done' %name)
    
    if __name__=='__main__':
        p=Process(target=test,args=('hello',))
        p.start()
        print('main')
    
    
    #开启子进程方式二
    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
        def __init__(self,name):
            super(MyProcess, self).__init__()
            self.name=name
    
        def run(self):
            print('%s is running' %self.name)
            time.sleep(3)
            print('%s is done' %self.name)
    
    if __name__=='__main__':
        p=MyProcess('hi')
        p.start()
        print('main')
    View Code

    5.进程中一些常见问题

    • 进程中不同进程间数据是互不联通通的
    • from multiprocessing import Process
      import os
      n=100
      
      def test():
          global n
          n=0
          print('%s进程中n=%s' %(os.getpid(),n))
      
      
      if __name__ == '__main__':
          p=Process(target=test)
          p.start()
          print('主进程中n=%s' %n)
      
      #主进程中n=100,没有被修改
      #子进程n=0,
      View Code
    • 守护进程:守护父进程,父进程结束后,守护进程无论是否结束都退出。守护进程要在start开启前,设置为守护进程后不能再开启子进程。
    • from multiprocessing import Process
      import time
      
      
      def test(name):
          print('%s为守护子进程staring'%name)
          time.sleep(3)
          print('%s为守护子进程ending' % name)
      
      if __name__=='__main__':
          p1=Process(target=test,args=('Hi',))
          p1.daemon=True
          p1.start()
          print('main')
      
      #仅输出main
      View Code
    • jion方法,会阻塞子进程,直到子进程完事后父进程才开启
    • from multiprocessing import Process
      import time
      
      def test(name):
          print('%s is running' %name)
          time.sleep(3)
          print('%s is done' %name)
      
      if __name__=='__main__':
          p=Process(target=test,args=('hello',))
          p.start()
          p.join()
          print('main')
      
      #hello is running
      #hello is done
      #main
      View Code

    6.进程互斥锁

    一个主进程中各子进程间数据是不能互相通信的,但可以通过访问外部同一个文件来实现共享,但共享带来的是竞争,竞争带来的结果就是混乱。解决方式就是加锁。

    from multiprocessing import Process, Lock
    import time
    import json
    import random
    import os
    
    
    def search():
        time.sleep(random.randint(1,3))
        dic=json.load(open('1.txt','r',encoding='utf-8'))
        print('%s 查询到余票%s' %(os.getpid(),dic['count']))
    
    def get():
        time.sleep(random.randint(1,3))
        dic=json.load(open('1.txt','r',encoding='utf-8'))
        if(dic['count']>0):
            dic['count']-=1
            time.sleep(random.randint(1,3))
            json.dump(dic, open('1.txt', 'w', encoding='utf-8'))
            print('%s购票成功'%os.getpid())
    
    def task(mutex):
        search()
        mutex.acquire()
        get()
        mutex.release()
    
    
    if __name__=='__main__':
        mutex=Lock() #设置锁
        for i in range(10):
            p=Process(target=task,args=(mutex,))
            p.start()
    View Code

    存在问题:加锁可以保证多个进程修改同一块数据时,只允许自有一个任务是可以修改,即串行修改,运行速度慢却保证了数据安全。该方式效率低(数据基于共享文件,而文件在磁盘上)、需要自己加锁处理。

    7.队列:实现进程间互相通信的方式

    队列是一种先进先出存储方式,

    from multiprocessing import Queue
    
    q=Queue(3)#定义一个队列大小,可以不指定
    q.put('first')   #插入数据,当队列满时会阻塞
    q.put({'count':1})
    q.put(1)
    q.put('de',block=True,timeout=3)
    print(q.get()) #拿数据
    View Code

    队列实现进程通信:

    from multiprocessing import Process,Queue
    
    def f1(q):
        q.put('hi')
    def f2(q):
        print(q.get())
    
    if __name__=='__main__':
        q=Queue()
        p=Process(target=f1,args=(q,))
        p1=Process(target=f2,args=(q,))
        p.start()
        p1.start()
    View Code

    8.生产者消费者模型

    在并发编程中使用生产者消费者模式可以解决大多数并发问题。通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者间不直接通信,而阻塞队列来进行通信,所以生产者生产玩数据后不用等待消费者的处理,直接扔给阻塞队列,消费者不用找生产者要数据,而直接从阻塞队列中取。阻塞队列就相当于一个缓冲区,平衡了消费者和生产者的能力。

    import time
    import random
    from multiprocessing import Process,Queue,JoinableQueue
    
    def producer(name,q):
        for i in range(3):
            r='包子%s' %i
            print('%s制作包子%s' %(name,i))
            time.sleep(random.randint(1, 3))
            q.put(r)
    
    def consumer(name,q):
        while True:
            res=q.get()
            if res=='NULL':break
            print('%s吃包子%s' %(name,res))
            time.sleep(random.randint(1, 3))
            q.task_done()
    
    
    if __name__=="__main__":
        #q=Queue()
        q=JoinableQueue()
        p=Process(target=producer,args=('gg',q,))
        p1 = Process(target=producer, args=('gg1', q,))
        c=Process(target=consumer,args=('cc',q))
        c1 = Process(target=consumer, args=('cc1', q))
        c2= Process(target=consumer, args=('cc2', q))
        p.start()
        p1.start()
    
        c.daemon=True
        c1.daemon=True
        c2.daemon=True
        c.start()
        c1.start()
        c2.start()
    
        p.join()
        p1.join()
        q.join()
    
        print('main')
    View Code

     

     

  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/2019zjp/p/12165877.html
Copyright © 2011-2022 走看看