進程與線程基本概念
在介紹Python使用線程之前,先簡單說下進程與線程的基本概念。進程是線程的容器,進程包含線程,進程是程序的實體。如下圖:
進程啓動後,默認裏面有一個線程,這個線程是主線程,從主線程啓動其它線程爲子線程。如果一個進程中沒有線程,那這個進程叫空進程,空進程是操作系統在全部線程執行結束後,沒有殺死進程,保留空進程是爲了下次啓動更快。
線程是程序執行的最小單元,在單個程序中同時運行多個線程完成不同的工作,稱爲多線程。
threading模塊
在Python創建線程,需要使用threading模塊
import threading
threading中常使用到的函數
函數名稱 | 說明 |
---|---|
active_count() | 返回當前活動線程對象數量 |
current_thread() | 返回當前線程對象 |
get_ident() | 返回當前線程ID |
enumerate() | 以列表形式返回當前所有活動的線程對象 |
main_thread() | 返回主線程對象 |
Python使用線程
創建一個線程需要創建一個Thread實例,以下是Thread的構造方法:
def __init__(self, group=None, target=None, name=None,args=(),
kwargs=None, *, daemon=None)
"""
target 線程執行的方法
name 線程名字
args 傳遞給線程執行方法的元組參數
kwargs 傳遞給線程執行方法的字典參數
"""
示例代碼:
# coding=utf-8
import threading
def doWork(num):
for i in range(num):
print(i, end=',')
if __name__ == '__main__':
t1 = threading.Thread(target=doWork, args=(10,))
t1.start()
t1.join()
這裏我們指定t1線程運行的方法是doWork就去,參數num是10,start
是運行線程,join
方法阻塞主線程等待子線程結束後再執行。
繼承Thread類:
# coding=utf-8
import threading
def doWork(num):
for i in range(num):
print(i, end=',')
class MyThread(threading.Thread):
def __init__(self, target, args):
threading.Thread.__init__(self)
self.target = target
self.args = args
def run(self):
self.target(self.args)
if __name__ == '__main__':
t1 = MyThread(target=doWork, args=10)
t1.start()
t1.join()
繼承Thread類,需要重寫run方法,調用start方法後,將執行run方法中的代碼.
GIL全局鎖
GIL(Global Interpreter Lock)全局解釋器鎖,當年龜叔在單核CPU上爲保證線程執行安全,在CPython中提供了全局解釋器鎖,當在CPython解釋器上執行Python代碼時,GIL會保護代碼的線程獨立使用共享數據,直到解釋器遇到I/O操作或操作次數到達上限時纔會釋放GIL。
CPython並沒有實現真正的多線程?
因爲GIL全局鎖的存在,在CPython解釋器上並沒有實現真正意義上的多線程,只是模擬多線程的狀態。如果想實現真正意義上的多線程,可以選擇Jython、IronPython、PyPy等其它Python解釋器。