標籤:怎樣 info 建立線程 自己 初始 強制 主線程 rgs from
什麼是進程通訊的訊號?
用過Windows的我們都知道,當我們無法正常結束一個程式時,可以用工作管理員強制結束這個進程,但這其實是怎麼實現的呢?同樣的功能在Linux上是通過產生訊號和捕獲訊號來實現的,運行中的進程捕獲到這個訊號然後作出一定的操作並最終被終止。訊號是UNIX和Linux系統響應某些條件而產生的一個事件,接收到該訊號的進程會相應地採取一些行動。通常訊號是由一個錯誤產生的。但它們還可以作為處理序間通訊或修改行為的一種方式,明確地由一個進程發送給另一個進程。一個訊號的產生叫產生,接收到一個訊號叫捕獲
什麼是線程鎖? 1.在單一進程的情況下可以叫單進程也可以叫單線程 2.線程鎖的大致思想是:如果線程A和線程B會執行執行個體的兩個函數a和b如果A必須在B之前運行,那麼可以在B進入b函數時讓B進入wait
set,直到A執行完a函數再把B從wait set中啟用。這樣就保證了B必定在A之後運行,無論在之前它們的時間先後順序是怎樣的。
3. 線程鎖用於必須以固定順序執行的多個線程的調度
線程鎖的思想是先鎖定後序線程,然後讓線序線程完成任務再解除對後序線程的鎖定。
訊號: 一個進程通過訊號的方式傳遞某種訊息, 接收方收到訊號後作出相應的處理 kill -sig pid:通過pid發送訊號殺死指定進程 kill -l:查看作業系統內所所有sig訊號關於訊號: 訊號名稱: 系統定義,名字或數字 訊號含義:系統定義,訊號的作用 預設處理方法: 當一個進程接收到訊號時,預設產生的效果 進程終止、暫停進程、忽略法發生 SIGHUP: 取消連結 SIGINT: Ctrl + c SIGQUIT: Ctrl + \ SIGTSTP : Ctrl + z SIGKILL: 終止進程且不能被處理 SIGSTOP: 暫停進程且不能被處理 SIGALRM: 時鐘訊號 SIGCHLD: 子進程改變狀態時父進程會收到此訊號 Python訊號處理:(signal模組) os.kill(pid,sig) 功能: 發送一個訊號給某個進程 參數: pid:給那個進程發送訊號(進程pid) sig:要發送的訊號類型 signal.alarm(sec) 功能: 非同步執行 設定時鐘訊號 在一定時間後給自己發送一個SIGALRM訊號 一個進程只能掛起一個時鐘 重新掛起時鐘會覆蓋之前時鐘 參數: sec:時間(秒) signal.pause() 功能: 阻塞進程,等待一個訊號 signal.signal(sig,handler) 功能:訊號處理參數: sig:要處理的訊號 handler:訊號處理方法 可選值: SIG_DFL 表示使用預設方法處理 SIG_IGN 表示忽略這個訊號 func 自訂函數 自訂函數格式: def func(sig,frame): sig:收到的訊號frame:訊號結構對象 signal函數也是一個非同步處理函數,只要執行了該函數則進程任意時候接受到相應的訊號都會處理signal是不能處理SIGKILL 、SIGSTOP的父進程中可以使用 signal(SIGCHLD,SIG_IGN)將子進程的退出交給系統處理 程式的非同步和同步執行: (單進程的同步非同步) 同步: 程式按照步驟一步步執行,呈現一個先後性的順序 非同步: 訊號是唯一一個內部通訊方式 程式在執行中利用核心功能協助完成必要的輔助操作 不影響應用程式層的持續執行 訊號是一種非同步進程間通訊方法 樣本:
from signal import * import time def handler(sig,frame): # 自訂處理訊號 if sig == SIGALRM: # 判斷訊號類型 print("收到時鐘訊號") elif sig == SIGINT: print("就不結束 略略略~")alarm(5) # 設定5秒時鐘訊號signal(SIGALRM,handler)signal(SIGINT,handler) # Ctrl + Cwhile True: print("Waiting for a signal") time.sleep(2)
訊號量: 給定一定的數量,對多個進程可見, 並且多個進程根據訊號量的多少確定不同行為 sem = Semaphore(num) 功能:建立訊號量參數:訊號量初始值傳回值:訊號量對象 sem.acquire() 將訊號數量減1 當數量為0時阻塞 sem.release() 將訊號量加1 sem.get_value() 擷取當前訊號量的值(數量) 同步互斥機制 目的: 解決對共有資源產生的資源爭奪 臨界資源: 多個進程或線程都可以操作的資源 臨界區: 操作臨界資源的程式碼片段 同步: 同步是一種合作關係,為完成某個任務,多進程或者多個線程之間形成的一種協調按照約定執行,相互告知,共同完成任務 互斥: 互斥是一種制約關係,當一個進程或者線程進入臨界區操作資源時採用上鎖的方式,阻止其他進程操作,直到解鎖後才能讓出資源 Event事件: from multiprocessing import Event 建立事件對象 e = Event() 事件阻塞 e.wait([timeout]) 功能: 使進程處於阻塞狀態,直到事件對象被set 事件設定: e.set.() 功能: 讓事件對象變為被設定狀態 清除設定: e.clear() 功能:使事件對象清除設定狀態 事件判斷: e.is_set() 判斷當前事件是否被set 樣本:
from multiprocessing import Process,Event from time import sleepdef wait_event(file): print("準備操作臨界資源") e.wait() # 等待主進程執行結束後set print("開始操作臨界資源",e.is_set()) fw = open(‘1.jpg‘,‘wb‘) with open(file,‘rb‘) as f: # 複製圖片 fw.write(f.read())def wait_event_timeout(file): print("也想操作臨界資源") e.wait(2) # 等待主進程執行set並進行2秒逾時檢測 if e.is_set(): print("也開始操作臨界資源") fw = open(‘2.jpg‘,‘wb‘) with open(file,‘rb‘) as f: # 複製圖片 fw.write(f.read()) else: print("等不了了,不等了")# 建立事件e = Event()path = "/home/tarena/file.jpg"file = ‘file.jpg‘# 建立兩個進程分別複製兩個圖片p1 = Process(target = wait_event,args = (file,))p2 = Process(target = wait_event_timeout,args = (file,))p1.start()p2.start()# 主進程先複製圖片 讓子進程進入wait狀態print("主進程在操作臨界資源")sleep(3)fw = open(file,‘wb‘)with open(path,‘rb‘) as f: fw.write(f.read())fw.close()e.set() # 子進程setprint("主進程操作完畢")p1.join()p2.join()
鎖 Lookmultiprocessing --> Look 建立對象: Lock = Lock() lock.acquire() 上鎖 lock.release() 解鎖 如果一個鎖對象已經被上鎖再調用則會阻塞 multiprocessing 建立的子進程不能用input 會報錯 樣本:
from multiprocessing import Process,Lock import sys from time import sleep #sys.stdout作為標準輸出資料流是多個進程共有的資源def writer1(): lock.acquire() #上鎖 for i in range(5): sleep(1) sys.stdout.write("writer1輸出\n") lock.release() #解鎖# 雖然都sleep1秒但是 若不加鎖會每1秒列印兩次# 由於上鎖原因 w1執行完臨界區w2才能被執行 一秒一次def writer2(): with lock: for i in range(5): sleep(1) sys.stdout.write("writer2輸出\n")#建立鎖lock = Lock()w1 = Process(target = writer1)w2 = Process(target = writer2)w1.start()w2.start()w1.join()w2.join()
多線程: 什麼是線程(thread) 線程也是一種多任務編程方式,可以使用電腦的多核資源 線程被稱為輕量級的進程 線程的特徵: 1.一個進程可以包含多個線程 2.線程是電腦核心使用的最小單位 3.線程也是一個運行過程,也要消耗電腦資源 4.多個線程共用共用進程的資源 5.線程也有自己的特徵屬性,TID、指令集、線程棧 6.多個線程之間獨立運行互不干擾 空間不獨立(都消耗進程空間) 7.線程的建立刪除消耗的資源要小於進程 線程/進程(1/20) threading 模組 threshold.Thread() 功能: 建立線程對象 參數: target 線程函數 name 線程名 預設為Thread-1... args 元組給線程函數位置傳參 kwargs 字典給線程函數索引值傳參 傳回值: 線程對象 t.start() 啟動線程 t.join() 回收線程 線程對象屬性: t.name 線程名 t.setName() 設定線程名稱 t.is_alive()查看線程狀態 threading.currentThread() 擷取當前進程對象 t.daemon屬性 預設False主線程的退出不會影響分支線程的執行 設定為True時主線程退出分支線程也退出設定daemon值 t.setDaemon(True) t.daemon = True查看daemon值 t.isDaemon 建立自己的線程類; 1.繼承Thread 2.載入父類__init__ 3.重寫run 樣本:
from threading import Thread from time import sleep, ctime# 建立一個MyThread類繼承Threadclass MyThread(Thread): def __init__(self, target, name = "Tedu", args = (), kwargs = {}): super().__init__() # 重新載入父類的__init__初始化方法 self.target = target self.name = name self.args = args self.kwargs = kwargs def run(self): # 在建立對象時自動調用run方法# 在調用run時調分支線程要執行的線程函數 以*元組和**字典的方式接收萬能傳參 self.target(*self.args, **self.kwargs)#線程函數def player(song,sec): for i in range(2): print("Playing %s : %s"%(song, ctime())) sleep(sec)# 用自訂類建立線程並執行t = MyThread(target = player, args = ("卡路裡", 3))t.start()t.join()
Python網路編程(進程通訊、訊號、線程鎖、多線程)