Python多进程,同步互斥,信号量,锁

发布时间:2019-03-10 19:53:53编辑:auto阅读(3303)

     

    进程补充

    进程间的信号

    信号是唯一的异步通信方法

    一个进程向另一个进程发送一个信号来传递某种信息,接受者根据传递的信息来做相应的事

    $ kill -l查看系统信号说明

    $ kill -9 pid号对进程发送信号

    信号名称 说明    
    1) SIGHUP 连接断开    
    2) SIGINT ctrl+c    
    3) SIGQUIT ctrl+\    
    20) SIGTSTP ctrl+z    
    9) SIGKILL 终止进程    
    19) SIGSTOP 暂停进程    
    26) SIGVTALRM 时钟信号    
    17) SIGCHLD 子进程退出时给父进程发的信号    
           

    在Python中import signal可以获取信号

    • os.kill(pid, sig)

      • 功能:发送信号

      • 参数

        • pid:要发送信号的PID号
        • sig :信号名称
        
       
       
       
       
       
       
       
       
       
       
       
     
      
    import os
    import signal
    os.kill(12345,signal.SIGKILL) #杀死进程
    View Code

     

    • signal.alarm(time)

      个人理解:把发送信号的信息告知系统内核,应用层程序继续运行,时间到之后利用内核告知应用层程序进行处理

    • 功能:非阻塞函数,向自身进程发送一个时钟信号
    • 参数:time->整型时间秒
    •  
        
        import signal
        import time
        signal.alarm(3)#3秒后向自身发送一个时钟信号
        while True:
            time.sleep(1)
            print("等待时钟信号")
            
        '''打印结果
        等待时钟信号
        等待时钟信号
        闹钟
        '''        
      View Code
       
        
        signal.alarm(3)#3秒后向自身发送一个时钟信号
        time.sleep(2)
        signal.alarm(5)#进程只有一个时钟信号,第二个会覆盖上面的时钟信号
        while True:
            time.sleep(1)
            print("等待时钟信号")
            
        '''打印结果
        等待时钟信号
        等待时钟信号
        等待时钟信号
        等待时钟信号
        闹钟
        '''
      View Code

       

      
      
    • signal.pause()
    • 功能:阻塞进程,然后等待信号
    • signal.signal(signum, handler)
    • 功能:处理信号
    • 参数
    • signum:要处理的信号

      • handler:信号的处理方法

        • SIG_DFL表示使用默认方法处理

        • SIG_IGN表示忽略这个信号

        • function表示传入一个函数,用指定的函数处理

          • def function(sig, frame)

            sig:捕获到的信号

            frame:信号对象

    View
      import signal
      from time import sleep
      
      signal.alarm(5)  # 5秒后向自身发送一个时钟信号
      # 使用信号的默认方法处理
      # signal.signal(signal.SIGALRM,signal.SIG_DFL)    
      # 忽略时钟信号
      # signal.signal(signal.SIGALRM,signal.SIG_IGN)
      # 忽略Ctrl+c信号
      # signal.signal(signal.SIGINT,signal.SIG_IGN)
      while True:
          sleep(2)
          print("等待时钟...")
    View Code

     

      # 使用自定义函数处理信号
      import signal
      from time import sleep
      
      def fun1(sig, frame):
          if sig == signal.SIGALRM :
              print("接收到时钟信号")
          elif sig == signal.SIGINT :
              print("ctrl+c就不结束")
      
      signal.alarm(5)  # 5秒后向自身发送一个时钟信号
      # 使用自定义函数处理信号
      # 处理时钟信号
      signal.signal(signal.SIGALRM,fun1)    
      # 处理ctrl+c信号
      signal.signal(signal.SIGINT,fun1)
      
      while True:
          print("等待")
          sleep(2)
          
      '''打印结果
      等待
      等待
      等待
      接收到时钟信号
      等待
      ...
      '''   
    View Code

     

    信号量(信号灯)

    原理:给定一个数量对多个进程可见,且多个进程都可以操作,进程可以对数量多少的判断执行各自的行为

    from multiprocessing import Semaphore

    • sem = Semaphore(num)

      • 功能:创建信号量
      • 参数:信号量的初始值
      • 返回值:信号量的对象
    • sem.get_value():获取信号量的值

    • sem.acquire():将信号量 -1,当信号为0时会阻塞

    • sem.release():将信号量 +1

      
    from multiprocessing import Semaphore, Process
    # 创建信号量对象
    sem = Semaphore(num)
    def fun():
        print("进程%d等待信号量"%os.getpid())
        # 消耗一个信号量
        sem.acquire()
        print("进程%d消耗信号量"%os.getpid())
        # 添加一个信号量
        sem.release()
        print("进程%d添加信号量"%os.getpid())
    
    jobs = []
    for i in range(4):
        p = Process(target = 4)
        jobs.append(p)
        p.start()
    for i in jobs:
        i.join()
    print(sem.get_value())
    View Code

     

    进程的同步互斥

    临界资源:多个进程或者线程都能操作的共享资源

    临界区:操作临界区资源的代码段

    同步:同步是一种合作关系,为完成某个任务,多进程或者多线程之间形成的一种协调关系

    互斥:互斥是一种制约关系,

    Event事件

    from multiprocessing import Event

    • e = Event():创建一个事件对象
    • e.wait([timeout]):设置事件阻塞
    • e.set():事件设置,当事件被设置后e.wait()不再阻塞,等于释放资源区
    • e.clear():清除设置,当事件被设置e.clear()后,e.wait()又会阻塞,阻塞资源区
    • e.is_set():事件状态判断,判断事件是否处于被设置的状态
      
     
    from multiprocessing import Event
    # 创建事件对象
    e = Event()
    # 查看
    print(e.is_set())        # False
    e.set()
    print(e.is_set())        # True
    e.wait(3)
    print(e.is_set())        # True
    e.clear()
    print(e.is_set())        # False
    View Code
    from multiprocessing import Event,Process
    from time import sleep
    
    def wait_event1():
        print("1想操作临界区资源")
        e.wait()
        print("1开始操作临界区资源",e.is_set())
        with open("file") as f:
            print(f.read())
    def wait_event2():
        print("2也想操作临界区资源")
        # 超时3秒检测
        e.wait(3)
        # 判断是否被设置
        if e.is_set():
            print("2开始操作临界区资源",e.is_set())
            with open("file") as f:
                print(f.read())
        else:
            print("2不能操作")       
    
    # 创建事件对象
    e = Event()
    p1 = Process(target = wait_event1)
    p2 = Process(target = wait_event2)
    p1.start()
    p2.start()
    print("主进程操作")
    with open("file",'w') as f:
        f.write("HELLO WORD")
    
    # 延迟4秒释放临界区
    sleep(4)
    # 释放临界区资源
    e.set()
    print("释放临界区")
    p1.join()
    p2.join()
    View Code 

    Lock 锁

    from multiprocessing import Lock

    • lock = Lock():创建一个锁对象
    • lock.acquire():上锁,如果已经是上锁状态,调用此函数会阻塞
    • lock.release():解锁
      
    from multiprocessing import Lock,Process
    import sys
    def writer1():
        # 上锁
        lock.acquire()
        for i in range(20):
            sys.stdout.write("writer1111\n")
        # 解锁
        lock.release() 
    def writer2():
        # 上锁
        lock.acquire()
        for i in range(20):
            sys.stdout.write("writer2222\n")
        # 解锁
        lock.release()
    lock = Lock()
    
    w1 = Process(target = writer1)
    w2 = Process(target = writer2)
    
    w1.start()
    w2.start()
    w1.join()
    w2.join()
    View Code

    第二种方法

    使用with语句上锁,with语句执行完毕后会自动解

    with lock:
        .....
        .....
        
     

     

     

     

     

关键字