python 多进程和多线程
生活随笔
收集整理的這篇文章主要介紹了
python 多进程和多线程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
python 多進程和多線程
一、進程和線程
1、概念
進程: 一個進程就是一個任務,可以理解為一個程序。一個進程可以有多個線程,至少一個。多進程中,同一個變量,各自有一份拷貝存在于每個進程中,互不影響。
線程: 多線程中,所有變量都由所有線程共享,任何一個變量都可以被任何一個線程修改。
2、優缺點
進程: 創建進程開銷(時間和空間)較大,一個子進程崩潰了,不會影響主進程和其他子進程。
線程: 創建線程開銷(時間和空間)相對較小,任何一個線程掛掉都可能直接造成整個進程崩潰。
二、多進程
1、使用多進程
from multiprocessing import Process import osdef run_proc(name):"""子進程函數"""print('Run child process %s: %s...' % (name, os.getpid()))if __name__ == '__main__':# 主進程 idprint('Parent process: %s.' % os.getpid())# 創建子進程p = Process(target=run_proc, args=('test',))print('Child process will start.')# 開啟子進程p.start()# 等待子進程運行結束p.join()print('Child process end.')2、進程池
from multiprocessing import Pool import os import time import randomdef task(name):"""任務函數"""print('Run task %s : %s...' % (name, os.getpid()))start = time.time()time.sleep(random.random() * 3)end = time.time()print('Task %s runs %0.2f seconds.' % (name, (end - start)))if __name__ == '__main__':# 主進程 idprint('Parent process %s.' % os.getpid())# 指定進程池中進程最大個數,默認為電腦的核數p = Pool(4)# 同時開啟 5 個進程for i in range(5):p.apply_async(task, args=(i,))print('Waiting for all subprocesses done...')# 關閉線程池,不再繼續添加新的Processp.close()# 等待所有子進程執行完畢p.join()print('All subprocesses done.')3、進程間通信:Queue
from multiprocessing import Process, Queue import os import time import randomdef write(q):"""添加數據到隊列中"""print('Process to write: %s' % os.getpid())for value in ['A', 'B', 'C']:print('Put %s to queue...' % value)q.put(value)time.sleep(random.random())def read(q):"""從隊列中讀取數據"""print('Process to read: %s' % os.getpid())while True:# 讀取數據,隊列為空時,True:會進入等待狀態,直到超時,False:拋出 Empty 異常value = q.get(True)print('Get %s from queue.' % value)if __name__ == '__main__':# 父進程創建Queue,并傳給各個子進程:q = Queue()# 創建兩個進程pw = Process(target=write, args=(q,))pr = Process(target=read, args=(q,))# 啟動子進程 pw 寫入pw.start()# 啟動子進程 pr 讀取pr.start()# 等待 pw 結束:pw.join()# pr進程是死循環,無法等待其結束,只能強行終止:pr.terminate()三、多線程
1、使用多線程
import threading import timedef loop():"""子線程任務函數"""print('thread %s is running...' % threading.current_thread().name)time.sleep(2)print('thread %s ended.' % threading.current_thread().name)if __name__ == '__main__':# 主線程名print('thread %s is running...' % threading.current_thread().name)# 創建子線程t = threading.Thread(target=loop, name='LoopThread')# 開啟子線程t.start()# 等待子線程運行完畢t.join()print('thread %s ended.' % threading.current_thread().name)2、線程鎖
import threadingbalance = 0 lock = threading.Lock()def change_it(n):"""先加后減,結果應該為 0"""global balancebalance = balance + nbalance = balance - ndef run_thread(n):"""子線程任務函數"""for i in range(100000):# 先要獲取鎖lock.acquire()try:# 只有獲得鎖的線程才能進行調用change_it(n)finally:# 用完一定要釋放鎖,這樣別的線程才有機會使用lock.release()if __name__ == '__main__':# 創建線程t1 = threading.Thread(target=run_thread, args=(5,))t2 = threading.Thread(target=run_thread, args=(8,))# 開啟線程t1.start()t2.start()# 線程阻塞t1.join()t2.join()print(balance)3、全局鎖:GIL 鎖
- Python的線程雖然是真正的線程,但解釋器執行代碼時,有一個GIL鎖:Global Interpreter Lock,任何Python線程執行前,必須先獲得GIL鎖,然后,每執行100條字節碼,解釋器就自動釋放GIL鎖,讓別的線程有機會執行。這個GIL全局鎖實際上把所有線程的執行代碼都給上了鎖,所以,多線程在Python中只能交替執行,即使100個線程跑在100核CPU上,也只能用到1個核。
- Python 雖然不能利用多線程實現多核任務,但可以通過多進程實現多核任務。多個Python 進程有各自獨立的GIL鎖,互不影響。
4、線程自己的全局變量:ThreadLocal
import threading# 創建全局 ThreadLocal 對象 local_school = threading.local()def process_student():"""獲取當前線程關聯的全局變量 student"""# 獲得各自線程的全局變量std = local_school.studentprint('Hello, %s (in %s)' % (std, threading.current_thread().name))def process_thread(name):"""子線程任務函數"""# 綁定 ThreadLocal 的student:local_school.student = nameprocess_student()if __name__ == '__main__':t1 = threading.Thread(target=process_thread, args=('A',), name='Thread-A')t2 = threading.Thread(target=process_thread, args=('B',), name='Thread-B')t1.start()t2.start()t1.join()t2.join()>>> Hello, A (in Thread-A)Hello, B (in Thread-B)GOOD LUCK!
總結
以上是生活随笔為你收集整理的python 多进程和多线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 8除以2表示什么意思_八字中劫财,比肩分
- 下一篇: Python 生成器(yield)