Python多进程,同步互斥,信号量,锁补充上一篇文章

 

进程补充

进程间的信号

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

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

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

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

信号名称说明  
1) SIGHUP连接断开  
2) SIGINTctrl+c  
3) SIGQUITctrl+\  
20) SIGTSTPctrl+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:
    .....
    .....
    
 

 

 

 

 

转载于:https://www.cnblogs.com/BanL/p/9642216.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者消费者问题是多进程并发编程中的一个经典问题,解决该问题的方法之一是使用信号量Python中的multiprocessing模块提供了Semaphore类来实现信号量。 在生产者消费者问题中,有两种角色:生产者和消费者。生产者负责生产数据,消费者负责消费数据。当生产者生产数据时,需要保证消费者不会消费同一个数据,当消费者消费数据时,需要保证生产者不会生产同一个数据。这就需要使用信号量来进行同步控制。 以下是一个使用信号量处理生产者消费者问题的Python程序示例: ```python import multiprocessing import time import random class Producer(multiprocessing.Process): def __init__(self, queue, semaphore): multiprocessing.Process.__init__(self) self.queue = queue self.semaphore = semaphore def run(self): for i in range(5): self.semaphore.acquire() item = random.randint(0, 100) print("Producer produced item: ", item) self.queue.put(item) time.sleep(1) class Consumer(multiprocessing.Process): def __init__(self, queue, semaphore): multiprocessing.Process.__init__(self) self.queue = queue self.semaphore = semaphore def run(self): while True: self.semaphore.acquire() if not self.queue.empty(): item = self.queue.get() print("Consumer consumed item: ", item) self.semaphore.release() if __name__ == '__main__': queue = multiprocessing.Queue() semaphore = multiprocessing.Semaphore(1) producer = Producer(queue, semaphore) consumer = Consumer(queue, semaphore) producer.start() consumer.start() producer.join() consumer.join() ``` 在该示例中,Producer类和Consumer类都继承了multiprocessing.Process类,用于创建子进程。Producer类负责生产数据,Consumer类负责消费数据。在run()方法中,使用semaphore.acquire()方法获取信号量,表示该进程需要占用资源。当生产者生产数据时,先获取信号量,然后将数据放入队列中。当消费者消费数据时,先获取信号量,然后判断队列是否为空,如果不为空,则从队列中取出数据进行消费。最后,都使用semaphore.release()方法释放信号量,表示该进程不再占用资源。 在主函数中,首先创建了一个队列和一个信号量,然后创建了一个生产者进程和一个消费者进程,分别启动这两个进程并等待它们执行完毕。运行该程序,可以看到生产者生产数据,消费者消费数据,并且保证不会出现重复的数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值