Python之程序與執行緒
阿新 • • 發佈:2022-01-24
程序與多執行緒
1. 程序
1.1 什麼是程序
- 程序是作業系統分配記憶體資源的最小單位
- 一個程序之內會預設有一個執行緒
- 程序是Python程式中執行多工的一種方式
1.2 多程序的使用
- 程序建立的三步:
- 匯入包
import multiprocessing
- 建立程序
- 啟動程序
start
- 匯入包
import multiprocessing
import time
def dance():
for item in range(1, 5):
print ("跳舞...")
time.sleep(0.2)
pass
pass
def sing():
for item in range(1, 5):
print("唱歌...")
time.sleep(0.2)
pass
pass
if __name__ == "__main__":
# group 程序組,預設是None,一般不會使用
# target 所需要執行的任務
# name 程序名,預設是process-1,2,.....
# args 引數(元組型別)
dance_process = multiprocessing.Process(target=dance)
dance_process.start()
sing()
import multiprocessing
import time
def dance():
for item in range(1, 5):
print("跳舞...")
time.sleep(0.2)
pass
pass
def sing():
for item in range(1, 5):
print ("唱歌...")
time.sleep(0.2)
pass
pass
if __name__ == "__main__":
dance_process = multiprocessing.Process(target=dance)
sing_process = multiprocessing.Process(target=sing)
dance_process.start()
sing_process.start()
1.3 獲取程序的編號
- 獲取主程序和子程序編號
os.getpid()
- 在子程序內獲取他的父程序編號
os.getppid()
- 通過程序編號停止程序
os.kill(process_id, 9)
import multiprocessing
import time
import os
def dance():
dance_process_id = os.getpid()
print("dance程序編號: ", dance_process_id, multiprocessing.current_process)
dance_process_parent_id = os.getppid()
print("dance父程序編號: ", dance_process_parent_id)
for item in range(1, 5):
print("跳舞...")
time.sleep(0.2)
# 9 表示強行停止該程序
os.kill(dance_process_id, 9)
pass
pass
def sing():
sing_process_id = os.getpid()
print("sing程序編號: ", sing_process_id, multiprocessing.current_process)
for item in range(1, 5):
print("唱歌...")
time.sleep(0.2)
pass
pass
if __name__ == "__main__":
dance_process = multiprocessing.Process(target=dance)
sing_process = multiprocessing.Process(target=sing)
dance_process.start()
sing_process.start()
main_processs_id = os.getpid()
print("主程序編號: ", main_processs_id, multiprocessing.current_process)
1.3 程序執行帶有引數的執行方式
- 以元組的方式傳遞(
args
) - 以字典的方式傳遞(
kwargs
) - 以元組和字典的方式傳遞(
args
,kwargs
)
import multiprocessing
def show_info(name, age):
print(name, age)
pass
if __name__ == "__main__":
# 方式一
print_process = multiprocessing.Process(target=show_info, args=("一之瀨", 16))
print_process.start()
# 方式二
print_process2 = multiprocessing.Process(target=show_info, kwargs={"name": "周雪", "age": 18})
print_process2.start()
# 方式三
print_process3 = multiprocessing.Process(target=show_info, args=("付佳慧",), kwargs={"age": 19})
print_process3.start()
1.4 程序之間不共享資源
- 程序之間不共享資源的原因
if __name__ == __main__:
的兩個作用
import multiprocessing
import time
g_list = list()
def add_list():
for i in range(1, 5):
g_list.append(i)
time.sleep(0.2)
print(i)
pass
pass
def read_list():
print(g_list)
if __name__ == '__main__':
add_process = multiprocessing.Process(target=add_list)
read_process = multiprocessing.Process(target=read_list)
add_process.start()
# join 是當前程序下(主程序),只有當子程序執行完成之後,才得以往下執行
add_process.join()
read_process.start()
print(g_list)
if __name__ == __main__:
的兩個作用
- 避免外部導包執行該區域的程式碼
- 避免windows下,程序產生遞迴
1.5 主程序會等待子程序執行完才銷燬
- 如果子程序是一個死迴圈會怎麼辦?
- 主程序銷燬之前,銷燬子程序
- 讓子程序守護主程序,主程序銷燬子程序銷燬,子程序會依賴於子程序。
import multiprocessing
import time
g_list = list()
def rask():
for i in range(1, 10):
g_list.append(i)
time.sleep(0.2)
print(i)
pass
pass
if __name__ == '__main__':
rask_process = multiprocessing.Process(target=rask)
# 方式一:
# rask_process.daemon = True
rask_process.start()
time.sleep(1)
# 方式二;
rask_process.terminate()
print("over")
2. 執行緒
2.1 什麼是執行緒
- 執行緒是作業系統排程運算的最小單位,是程序的實際運作單位。
- 執行緒自己不擁有系統資源
- 同一個程序下面的執行緒能夠共享程序所擁有的的資源
- 一個執行緒能夠建立或撤銷另外一個程序。
- 同一個程序的多個執行緒能夠併發執行
- 執行緒是執行多工的一種方式
2.2 執行緒的使用
- 匯入
threading
模組 - 建立子執行緒
- 啟動子執行緒
import threading
import time
def sing():
for i in range(3):
print("sing...")
time.sleep(0.2)
pass
def dance():
for i in range(3):
print("dance...")
time.sleep(0.2)
pass
if __name__ == '__main__':
sing_thread = threading.Thread(target=sing)
sing_thread.start()
dance_thread = threading.Thread(target=dance)
dance_thread.start()
2.3 使用執行緒執行帶有引數的執行方式
- args
- kwargs
2.4 執行緒的注意事項
執行緒之間的執行順序是無序的
import threading
import time
def rask():
time.sleep(1)
print(threading.current_thread())
pass
if __name__ == '__main__':
for item in range(5):
rask_threading = threading.Thread(target=rask)
rask_threading.start()
pass
執行結果
<Thread(Thread-2, started 18756)>
<Thread(Thread-1, started 20816)>
<Thread(Thread-4, started 18496)>
<Thread(Thread-3, started 7556)>
<Thread(Thread-5, started 20920)>
主執行緒會等待子執行緒執行完結果
- 如果子執行緒是一個死迴圈的話?
- 讓子執行緒守護主執行緒
demaon
(就可以結束死迴圈)
import threading
import time
def rask():
while True:
print("正在執行中.....")
time.sleep(0.2)
pass
pass
if __name__ == '__main__':
# 方法一:
# rask_threading = threading.Thread(target=rask, daemon=True)
rask_threading = threading.Thread(target=rask)
# 方法二
rask_threading.setDaemon(True)
rask_threading.start()
time.sleep(1)
print("over")
執行緒之間是可以共享資料的
import threading
import time
g_list = list()
def add_list():
for item in range(5):
g_list.append(item)
print(item)
time.sleep(0.2)
pass
pass
def read_list():
print(g_list)
pass
if __name__ == '__main__':
add_thread = threading.Thread(target=add_list)
add_thread.start()
# 當前程序等待add_thread程序執行完之後,才能夠往下執行
add_thread.join()
read_thread = threading.Thread(target=read_list)
read_thread.start()
執行緒之間共享全域性變量出現錯誤的情況
- 兩個執行緒同時訪問全域性變數
import threading
import time
num = 0
def first():
for item in range(100000):
global num
num = num + 1
pass
print(num)
pass
def second():
for item in range(100000):
global num
num = num + 1
pass
print(num)
pass
if __name__ == '__main__':
first_thread = threading.Thread(target=first)
second_thread = threading.Thread(target=second)
first_thread.start()
# 解決方法
first_thread.join()
second_thread.start()
2.5 互斥鎖
lock = threading.Lock()
- 上鎖
lock.acquire()
- 釋放鎖
lock.release
import threading
import time
num = 0
lock = threading.Lock()
def first():
lock.acquire()
for item in range(100000):
global num
num = num + 1
pass
lock.release()
print("rask1:", num)
pass
def second():
lock.acquire()
for item in range(100000):
global num
num = num + 1
pass
lock.release()
print("rask2:", num)
pass
if __name__ == '__main__':
first_thread = threading.Thread(target=first)
second_thread = threading.Thread(target=second)
first_thread.start()
second_thread.start()
第一次寫部落格,後續會慢慢更新