進程和線程
進程(Process)是計算機中的程序關于數據集合上的一次活動,是系統進行資源分配和調度的基本單位。簡單的說,進程是正在運行的程序的實例。
一般來說,進程一般由文本區域、數據區域和堆棧組成。文本區域存儲處理器執行的代碼,數據區域存儲變量和進程執行期間使用的動態分配的內存,堆棧則存儲活動過程中調用的指令和本地變量。
線程(Thread)是程序執行流的最小單元,線程只擁有運行所必須的資源,其他的資源和該進程中的其他線程共享。有時也被稱之為輕量級進程(LightWeight Process,LWP)。一般一個進程中都有一個主線程。
各自優缺點:
進程擁有獨立的地址空間和資源,進程間通信IPC比較麻煩,當一個進程崩潰后,不會對其他進程造成影響,故多進程程序比較健壯。但進程間切換耗費的資源比較大,時間較長。
線程由于共享所屬進程的資源,故線程間通信比較簡單。線程所擁有的資源比較少,線程間的切換耗時短。
PIL
說起python和線程,那就不得不說一下PIL了,PIL是全局解釋器鎖(Global Interpreter Lock),該鎖保證同時只能有一個線程運行。
在多線程中,python虛擬機的運行方式如下:
1. 設置GIL
2. 切換進一個線程運行
3. 執行一下一個操作:
- 指定數量的字節碼指令
- 線程主動讓出控制權
4. 切換線程
5. 解鎖GIL
對于python來說,GIL會在線程進行I/O調用前被釋放,以便其他的線程運行,這也就是Python更適合做I/O密集型的工作。
python中提供了多個模塊來支持多線程編程,如thread,threading,Queue模塊,其中thread模塊提供了基本的線程和鎖定支持,threading提供了更高級別、功能更全面的線程管理,Queue模塊可以創建隊列數據結構,在多個線程之間進行數據共享。
thread模塊
函數方法 | 描述 |
---|---|
thread模塊函數 | |
start_new_thread(function,args,kwargs=None) | 派生一個新的線程 |
allocate_lock() | 分配LockType鎖對象 |
exit() | 退出線程 |
LockType鎖對象方法 | |
acquire(wait=None) | 獲取鎖對象 |
locked() | 是否獲取鎖對象 |
release() | 釋放鎖對象 |
一般來說thread不常用,原因如下:
- thread模塊中所擁有的同步元語只有一個,即LockType,
- thread對于進程的進入退出沒有控制,當主線程結束時,所有的其他線程也會強制結束,不會發出警告或清理。
- 不支持守護線程
- thread所支持的操作很少
在python3中thread模塊被更名為_thread
下面給出一個python3關于_thread的簡單例子:
import _thread
import random
from time import ctime, sleep
def loop(nloop, nsec, lock):
print('start loop:', nloop, 'nsec:', nsec, 'at:', ctime())
sleep(nsec)
print('end loop', nloop, 'done at:', ctime())
lock.release()
def main():
print('starting at:', ctime())
locks = []
for i in range(2):
lock = _thread.allocate_lock()
lock.acquire()
locks.append(lock)
for i in range(2):
_thread.start_new_thread(loop, (i, random.randint(1, 4), locks[i]))
for i in range(2):
while locks[i].locked():
pass
print('all down at:', ctime())
if __name__ == '__main__':
main()
在這個例子中,首先通過_thread_allocate_lock()來生成鎖對象,并通過acquire()來獲取鎖,這樣就相當于將鎖鎖上,然后將該鎖傳遞給每個線程中。
線程中操作很簡單,休眠傳遞過來的時間,然后釋放鎖。
在主線程中,不停的去判斷兩個鎖是否鎖住,避免主線程執行完導致兩個線程直接被強制結束。運行的結果如下:
starting at: Thu Sep 7 09:57:36 2017
start loop: 0 nsec: 2 at: Thu Sep 7 09:57:36 2017
start loop: 1 nsec: 4 at: Thu Sep 7 09:57:36 2017
end loop 0 done at: Thu Sep 7 09:57:38 2017
end loop 1 done at: Thu Sep 7 09:57:40 2017
all down at: Thu Sep 7 09:57:40 2017
python多線程就暫時講到這里了。