1. 程式人生 > >Python多進程,同步互斥,信號量,鎖補充上一篇文章

Python多進程,同步互斥,信號量,鎖補充上一篇文章

python多進程 text stdout 執行 pause mat 1.7 hit splay

進程補充進程間的信號信號量(信號燈)進程的同步互斥Event事件Lock 鎖

進程補充

進程間的信號

信號是唯一的異步通信方法

一個進程向另一個進程發送一個信號來傳遞某種信息,接受者根據傳遞的信息來做相應的事

$ 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:
    .....
    .....
    

Python多進程,同步互斥,信號量,鎖補充上一篇文章