学习笔记(二十二)—— 了解进程和线程
文章目錄
- 一、進程
- 1.1、什么是程序
- 1.2、了解進程
- 1.3、進程的三種狀態
- 1.4、多進程
- 二、線程
- 2.1、了解線程
- 2.2、了解多線程
- 2.3、進程與線程的區別
- 2.4、多線程實現
- 2.5、線程鎖
- 2.6、全局解釋鎖(GIL)
一、進程
1.1、什么是程序
程序是指令和數據的有序集合,其本身沒有任何運行的含義,是一個靜態的概念。而進程則是在處理機上的一次執行過程,它是一個動態的概念。這個不難理解,其實進程是包含程序的,進程的執行離不開程序,進程中的文本區域就是代碼區,也就是程序。
1.2、了解進程
進程就是一段程序的執行過程。它是一個具有一定獨立功能的程序關于某個數據集合的一次運行活動。它是操作系統動態執行的基本單元,在傳統的操作系統中,進程既是基本的分配單元,也是基本的執行單元。
簡單的來講進程的概念主要有兩點:
① 進程是一個實體。每一個進程都有它自己的地址空間,一般情況下,包括文本區域(textregion)、數據區域(dataregion)和堆棧(stackregion)。文本區域存儲處理器執行的代碼;數據區域存儲變量和進程執行期間使用的動態分配的內存;堆棧區域存儲著活動過程調用的指令和本地變量。
② 進程是一個“執行中的程序”。程序是一個沒有生命的實體,只有處理器賦予程序生命時,它才能成為一個活動的實體,我們稱其為進程。
1.3、進程的三種狀態
進程有三個狀態,就緒、運行和阻塞。
- 就緒態:其實就是獲取了除cpu外的所有資源,只要處理器分配資源就可以馬上執行。
- 運行態:獲得了處理器分配的資源,程序開始執行。
- 阻塞態:當程序條件不夠時候,需要等待條件滿足時候才能執行,如等待i/o操作時候,此刻的狀態就叫阻塞態。
1.4、多進程
Python中的多進程是通過multiprocessing包來實現的,和多線程的threading.Thread差不多,它可以利用multiprocessing.Process對象來創建一個進程對象。這個進程對象的方法和線程對象的方法差不多也有start(),run(), join()等方法,其中有一個方法不同Thread線程對象中的守護線程方法是setDeamon,而Process進程對象的守護進程是通過設置daemon屬性來完成的。
Python多進程的實現方法,和多線程類似
實現示例:
結果:
0進程開啟了 1進程開啟了 2進程開啟了 3進程開啟了 4進程開啟了join方法:是讓主進程等待子進程運行完畢后再執行主進程的。(即主進程阻塞)
類的方式創建線程
Process類的其他方法
構造方法: Process([group [, target [, name [, args [, kwargs]]]]])group: 線程組 target: 要執行的方法name: 進程名args/kwargs: 要傳入方法的參數實例方法:is_alive():返回進程是否在運行,bool類型。join([timeout]):阻塞當前上下文環境的進程程,直到調用此方法的進程終止或到達指定的timeout(可選參數)。start():進程準備就緒,等待CPU調度run():strat()調用run方法,如果實例進程時未制定傳入target,這star執行t默認run()方法。terminate():不管任務是否完成,立即停止工作進程屬性:daemon:和線程的setDeamon功能一樣name:進程名字pid:進程號二、線程
2.1、了解線程
通常在一個進程中可以包含若干個線程,當然一個進程中至少有一個線程,不然沒有存在的意義。線程可以利用進程所擁有的資源,我們把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位。
2.2、了解多線程
多線程是為了同步完成多項任務,不是為了提高運行效率,而是為了提高資源使用效率來提高系統的效率。線程是在同一時間需要完成多項任務的時候實現的。
多線程就像火車的每一節車廂,而進程則是火車。車廂離開火車是無法跑動的,同理火車也不可能只有一節車廂。多線程的出現就是為了提高效率。
2.3、進程與線程的區別
進程和線程的主要差別在于它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發操作,只能用線程,不能用進程。
2.4、多線程實現
Python的標準庫提供了兩個模塊:_thread和threading,_thread是低級模塊,threading是高級模塊,對_thread進行了封裝。絕大多數情況下,我們只需要使用threading這個高級模塊。啟動一個線程就是把一個函數傳入并創建Thread實例,然后調用start()開始執行。
補充知識點:主線程和子線程
程序執行時,程序本身就是一個線程,叫主線程。
手動創建的線程,叫子線程。
主線程的執行中不會等待子線程執行完畢,就會直接執行后面的代碼創建線程。
實現示例:
from threading import Thread import timedef run(name):print(name,'線程執行了!')time.sleep(4) #創建線程 t1 = Thread(target=run,args=('t1',)) t2 = Thread(target=run,args=('t2',)) #啟動線程 t1.start() t2.start()----結果: t1 線程執行了! t2 線程執行了!類的方式創建線程
from threading import Thread import timeclass MyThread(Thread):def __init__(self,name):super(MyThread,self).__init__()self.name = namedef run(self):print(self.name, '線程執行了!')time.sleep(4)t1 = MyThread('t1') t2 = MyThread('t2') t1.start() t2.start()其他方法:
isAlive(): 返回線程是否活動的。 getName(): 返回線程名。 setName(): 設置線程名。 threading模塊提供的一些方法: threading.currentThread(): 返回當前的線程變量。 threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啟動后、結束前,不包括啟動前和終止后的線程。 threading.activeCount():返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。2.5、線程鎖
多線程可以同時運行多個任務但是當多個線程同時訪問共享數據時,可能導致數據不同步,甚至錯誤!因此,就要使用線程鎖。
線程鎖:當有多個線程訪問同一對象的加鎖方法/代碼塊時,同一時間只有一個線程在執行,其余線程必須要等待當前線程執行完之后才能執行該代碼段。但是,其余線程是可以訪問該對象中的非加鎖代碼塊的。
用法
#創建鎖 lock = threading.Lock() #鎖定 lock.acquire([timeout]) #釋放 lock.release()優缺點
優點:保證資源同步
缺點:
等待肯定會慢
示例
import time import threadinglock = threading.Lock() num = 100 #出售 def sail(name):lock.acquire() #上鎖global numif num>0:num-=1print(name,'出售了一張電影票,還剩:',num,'張')lock.release() #釋放鎖#售票 while True:if num>0:A = threading.Thread(target=sail, args=('A售票員',))B = threading.Thread(target=sail, args=('B售票員',))A.start()B.start()else:break2.6、全局解釋鎖(GIL)
不管系統CPU核心是多少,都保證python程序中同一時間點只能執行一個線程。它本本意上是為了實現數據安全問題,但從結果上卻造成了cpu資源上的浪費,影響了程序執行的效率,因此弊大于利。(重點記)
我們可以通過使用多進程來解決GIL所造成的問題
總結
以上是生活随笔為你收集整理的学习笔记(二十二)—— 了解进程和线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习笔记(二十)—— 网络编程
- 下一篇: 数据结构与算法笔记(一)—— 引入概念、