程序物件、殭屍程序與孤兒程序、守護程序、互斥鎖

认真的六六發表於2024-06-24

pycharm啟用碼網站:http://idea.medeming.com/jets/

一臺計算機上面執行著很多程序,那麼計算機是如何區分並管理這些程序的呢?

  # 計算機會給每一個執行的程序分配一個PID號(PID號(程序號):也是唯一的)
  # 如何檢視?
    1. window電腦,加入cmd,輸入tasklist,然後回車,即可檢視當前計算機上面所有執行的程序
    2. mac電腦,輸入ps -aux,然後回車,即可檢視當前計算機上面所有執行的程序

 # 如何在這麼多程序號裡查到自己想要的那個程序號呢?
    1. window系統:tasklist|findstr 程序號
    2. mac系統:ps -aux|grep 程序號

 1 import os
 2 import time
 3 from multiprocessing import Process, current_process
 4 
 5 
 6 def task():
 7     print(
 8         '%s is running' % current_process().pid)  # 使用from multiprocessing import Process, current_process,檢視當前程序的PID程序號
 9     print('%s is running' % os.getpid())  # 使用os獲取當前程序號
10     print(f'{os.getppid()}子程序的主程序號')  # 檢視當前程序的父程序程序號
11     time.sleep(3)
12 
13 
14 if __name__ == '__main__':
15     p = Process(target=task)
16     p.start()
17     print('', current_process().pid)
18     print('主程序', os.getpid())
19     p.terminate()  # 殺手當前程序
20     time.sleep(0.2)  # 給系統時間去殺死當前程序,這時候下面程式碼才為False
21     print(p.is_alive())  # True,判斷當前程序是否存活,p.terminate()並不是立馬殺死,是告訴作業系統去幫你殺死當前程序,需要時間去殺死
22     '''
23     一般情況下我們會預設將儲存布林值的變數名和返回的結果是布林值的方法名,都起以成is——開頭
24     '''
25     # 如何在這麼多程序號裡查到自己想要的那個程序號呢?
26     # window系統:tasklist|findstr 程序號
27     # mac系統:ps -aux|grep 程序號

【殭屍程序與孤兒程序】

 1 import time
 2 from multiprocessing import Process
 3 
 4 
 5 def run():
 6     print('hello world')
 7     time.sleep(3)
 8     print('get out')
 9 
10 
11 if __name__ == '__main__':
12     p = Process(target=run)
13     p.start()
14     print('') # 主、 hello world、 get out
15 
16 
17 殭屍程序:程序執行完畢後並不會立刻銷燬所有的資料 會有一些資訊短暫保留下來
18     比如程序號、程序執行時間、程序消耗功率等給父程序檢視
19     所有的程序都會變成殭屍程序
20 什麼時候回收子程序佔用的pid號?
21     父程序等待子程序執行結束,父程序呼叫join方法
22 
23 
24 孤兒程序
25     子程序正常執行 父程序意外死亡 作業系統針對孤兒程序會派遣福利院管理

【守護程序】

 1 把專案程序做成某一個程序的守護程序,這樣即使專案因為意外原因掛掉,
 2 主程序只要不掛監測到後,又會將專案程序再起起來
 3 
 4 
 5 會隨著主程序的結束,守護程序立刻結束!!!
 6 
 7 
 8 使用場景:
 9 寫了一個多程序的python程式碼,把所有的子程序設成主程序的守護程序
10 這樣主程序一關,所有設成守護程序的子程序也全部關閉了,這樣節省計算機效率了!!!
11 需要做批次管理,一鍵關閉所有的程序,就可以把所有的子程序設成主程序的守護程序
12 
13 import time
14 from multiprocessing import Process
15 
16 
17 def task(name):
18     print('%s總管正在活著' % name)
19     time.sleep(3)
20     print('%s總管正在死了' % name)
21 
22 
23 if __name__ == '__main__':
24     p = Process(target=task, args=('alex',))
25     p.daemon = True  # 將程序p設定為守護程序,必須在start()方法呼叫之前設定,否則會報錯
26     p.start()
27     print('皇帝egon壽終正寢')

PS:守護程序關鍵字: daemon

【互斥鎖,模擬搶票】

  1 mutex:互斥鎖
  2 Only one task may hold the mutex at a time, and only this task can unlock the mutex.
  3 一次只能有一個任務持有互斥鎖,並且只有這個任務可以解鎖互斥鎖。
  4 -----------------------------------------
  5 互斥鎖的作用:將併發變成序列,犧牲了效率,但是保證了資料的安全!!
  6 
  7 互斥鎖:鎖不能濫用,建議只加在運算元據的部分,否則整個程式的效率會極低!!
  8 -------------------------------------------------------------------------------
  9 
 10 還是就模擬檔案裡面只有一張票的情況:{"ticket_num":1}
 11 ===============================================
 12 模擬搶票
 13 
 14 # 模擬搶票功能
 15 from multiprocessing import Process, Lock
 16 import json
 17 import time
 18 import random
 19 
 20 
 21 # 查票
 22 def search(i):
 23     # 檔案操作讀取票數
 24     with open(r'C:\Users\靳小潔\PycharmProjects\pythonProject\Day39\data.json', 'r', encoding='utf-8') as f:
 25         dic = json.load(f)
 26     print('使用者%s查詢到剩餘票數:%s' % (i, dic.get('ticket_num')))
 27 
 28 
 29 # 買票    1.先查  2.再買
 30 def buy(i):
 31     with open(r'C:\Users\靳小潔\PycharmProjects\pythonProject\Day39\data.json', 'r', encoding='utf-8') as f:
 32         dic = json.load(f)
 33         # 模擬網路延遲
 34         time.sleep(random.randint(1, 3))
 35         # 判斷當前是否有票
 36         if dic.get('ticket_num') > 0:
 37             # 修改資料庫 買票
 38             dic['ticket_num'] -= 1
 39             # 寫入資料庫
 40             with open(r'C:\Users\靳小潔\PycharmProjects\pythonProject\Day39\data.json', 'w', encoding='utf-8') as f:
 41                 json.dump(dic, f)
 42             print('使用者%s買到票' % i)
 43         else:
 44             print('使用者%s沒有買到票' % i)
 45 
 46 
 47 # 整合上面兩個函式,每個人都查票買票
 48 def run(i):
 49     # 查票
 50     search(i)
 51     buy(i)
 52 
 53 
 54 # 模擬多個人買票
 55 if __name__ == '__main__':
 56     for i in range(1, 11):
 57         p = Process(target=run, args=(i,))
 58         p.start()
 59 
 60 這時候發現10個人都檢視到了餘票且都買到了票,但是票只有一張,顯然是錯誤的
 61 
 62 
 63 ===============================================
 64 這時候我們就用到了鎖---互斥鎖Lock
 65 
 66 
 67 # 模擬搶票功能
 68 from multiprocessing import Process, Lock
 69 import json
 70 import time
 71 import random
 72 
 73 
 74 # 查票
 75 def search(i):
 76     # 檔案操作讀取票數
 77     with open(r'C:\Users\靳小潔\PycharmProjects\pythonProject\Day39\data.json', 'r', encoding='utf-8') as f:
 78         dic = json.load(f)
 79     print('使用者%s查詢到剩餘票數:%s' % (i, dic.get('ticket_num')))
 80 
 81 
 82 # 買票    1.先查  2.再買
 83 def buy(i):
 84     with open(r'C:\Users\靳小潔\PycharmProjects\pythonProject\Day39\data.json', 'r', encoding='utf-8') as f:
 85         dic = json.load(f)
 86         # 模擬網路延遲
 87         time.sleep(random.randint(1, 3))
 88         # 判斷當前是否有票
 89         if dic.get('ticket_num') > 0:
 90             # 修改資料庫 買票
 91             dic['ticket_num'] -= 1
 92             # 寫入資料庫
 93             with open(r'C:\Users\靳小潔\PycharmProjects\pythonProject\Day39\data.json', 'w', encoding='utf-8') as f:
 94                 json.dump(dic, f)
 95             print('使用者%s買到票' % i)
 96         else:
 97             print('使用者%s沒有買到票' % i)
 98 
 99 
100 # 整合上面兩個函式,每個人都查票買票
101 def run(i, mutex):
102     # 查票
103     search(i)
104     # 買票,給它加鎖處理
105     # 搶鎖
106     mutex.acquire()
107     buy(i)
108     # 釋放鎖
109     mutex.release()
110 
111 
112 # 模擬多個人買票
113 if __name__ == '__main__':
114     #  在主程序中建立一個鎖物件,讓所有的子程序搶
115     mutex = Lock()
116     for i in range(1, 11):
117         p = Process(target=run, args=(i, mutex))
118         p.start()

【佇列】

什麼是佇列:程序間通訊:佇列模組(Queue)

  佇列:先進先出

  堆疊:先進後出

 1 # 程序間通訊:佇列模組(Queue)
 2 from multiprocessing import Queue
 3 
 4 # 建立一個佇列
 5 q = Queue(4)  # ()可以傳數字,表示生成的佇列最大可以同時存放的資料量
 6 # 往佇列中存資料
 7 q.put(111)
 8 q.put(222)
 9 q.put(333)
10 q.put(444)
11 # q.put(555)  # 佇列滿了,put會阻塞,直到有位置讓出來,才不會阻塞
12 print(q.full())  # 判斷佇列是否滿了
13 print(q.empty())  # 判斷佇列是否為空
14 
15 # print(q.full())  # 判斷佇列是否滿了
16 
17 #  從佇列中取資料
18 v1 = q.get()
19 v2 = q.get()
20 v3 = q.get()
21 v4 = q.get()
22 # v5 = q.get()
23 v5 = q.get_nowwait()  # 沒有資料直接報錯
24 # v6=q.get(timeout=3) # 沒有資料的話,等待3秒,還是沒有的話,報錯
25 print(v1, v2, v3, v4, v5)  # 佇列中如果已經沒有資料的話,get取不到會阻塞
26 
27 # ==============總結
28 '''
29 q.full()
30 q.empty()
31 q.get_nowait()
32 這三種方法再多程序的情況下是不精確的
33 '''