1. 程式人生 > 其它 >Python學習-多執行緒和多程序

Python學習-多執行緒和多程序

@

目錄

基本概念

  1. 程序:程式的一次執行
  2. 執行緒:CPU的基本排程單位

執行緒

執行緒的建立

執行緒的建立主要通過threading模組

print('主執行緒開始')

from threading import Thread
import threading
from time import sleep

def sub_fun(arg1,arg2):
    print('子執行緒開始')
    print('子執行緒函式引數時:{0},{1}'.format(arg1,arg2))
    sleep(5)
    print('子程序結束')

thread = Thread(target=sub_fun, args=('引數1','引數2'))

thread.start()

thread.join()

print('主執行緒結束')

執行緒共享全域性變數和鎖

在一個程序內的所有執行緒共享全域性變數,很方便在多個執行緒間共享資料
缺點就是,執行緒是對全域性變數隨意遂改可能造成多執行緒之間對全域性變數的混亂(即執行緒非安全)

from threading import Thread
import time

num = 0 

def add1(n):
    global num
    for i in range(n):
        num = num+1
    print('in add1, num is {0}\n'.format(num))
    
def add2(n):
    global num
    for i in range(n):
        num = num+1
    print('in add2, num is {0}\n'.format(num))   

thread1 = Thread(target=add1, args=(1000000,))
thread1.start()

thread2 = Thread(target=add2, args=(1000000,))
thread2.start()

time.sleep(5)
print('final num is {0}\n'.format(num))

最後執行的結果是

in add2, num is 1295511
in add1, num is 1324484
final num is 1324484

對num加1,2000000次,結果卻不是2000000,這是由於執行緒共享全域性變數

在num=0時,thread1 thread2同時取得num=0。
此時thread1 sleeping,thread2 running, thread2使num=1
然後thread2 sleeping,thread1 running, thread1使num=1
這就導致兩個執行緒重複操作了兩次,num結果仍是1

簡單來說就是執行緒被覆蓋了,這時可以使用 threading庫裡面的鎖物件 Lock 去保護

lock = threading.Lock()

lock.acquire()
lock.release()

程序

程序的建立

在python中程序的建立主要通過Process函式
Process([group [, target [, name [, args [, kwargs]]]]])

  1. target:如果傳遞了函式的引用,可以任務這個子程序就執行這裡的程式碼
  2. args:給target指定的函式傳遞的引數,以元組的方式傳遞
  3. kwargs:給target指定的函式傳遞命名引數
  4. name:給程序設定一個名字,可以不設定
  5. group:指定程序組,大多數情況下用不到

Process建立的例項物件的常用方法:

  1. start():啟動子程序例項(建立子程序)
  2. is_alive():判斷程序子程序是否還在活著
  3. join([timeout]):是否等待子程序執行結束,或等待多少秒
  4. terminate():不管任務是否完成,立即終止子程序

Process建立的例項物件的常用屬性:

  1. name:當前程序的別名,預設為Process-N,N為從1開始遞增的整
  2. pid:當前程序的pid(程序號)
from multiprocessing import Process
import os
import time

def sub_fun():
        print('子程序執行中,pid=%d...' % os.getpid())

if __name__ == '__main__':
    print('父程序pid: %d' % os.getpid())
    for i in range(3):
        p = Process(target=sub_fun)
        p.start()

程序間的通訊

程序間有多種通訊機制,下面就常用的Queue為例進行說明

from multiprocessing import Process,Queue
import os,time,random

def write(q):
    for value in ['a','b','c']:
        print('put {0} to queue'.format(value))
        q.put(value)
        time.sleep(random.random())

def read(q):
    while not q.empty():#此處死迴圈,ctrl+c終止
        value = q.get(True)
        print('get {0} to queue'.format(value))
        q.put(value)
        time.sleep(random.random())

if __name__ == '__main__':
    q = Queue()

    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))

    pw.start()
    pw.join()

    pr.start()
    pr.join()

    print('-----ok------')