1. 程式人生 > 其它 >Python之程序與執行緒

Python之程序與執行緒

程序與多執行緒

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()

第一次寫部落格,後續會慢慢更新