Python的多線程

什麼是線程:

  • 線程也是一種多任務編程方法,可以利用計算機多核資源完成程序的併發執行。線程又被稱爲輕量級的進程。

線程的特徵:

  • 線程是計算機多核分配的最小單位
  • 一個進程可以包含多個線程
  • 線程也是一個運行的過程,消耗計算機資源,多個線程共享進程的資源和空間
  • 線程的創建刪除消耗的資源都要遠遠小於進程
  • 多個線程之間執行互不干擾
  • 線程也有自己的特有屬性,比如指令集 ID

Python中使用threading模塊創建線程

主要方法:

threading.Thread()

  • 功能:創建線程對象
  • 參數:name(線程名稱,默認Thread-1),target(線程函數),args(元組,給線程函數位置傳參),kwargs(字典,給線程函數鍵值傳參)

t.start()

  • 功能:啓動線程,自動運行線程函數

t.join([timeout])

  • 功能:回收線程
  • 參數(timeout):阻塞等待時間

線程對象屬性:

t.is_alive()

  • 功能:查看線程狀態

t.setName()

  • 功能:設置線程名稱

t.getName() 或者 t.name

  • 功能:獲取線程名稱

threading.currentThread()

  • 功能:獲取當前線程對象

t.daemon屬性

  • 默認情況主線程退出不會影響分支線程執行,如果設置爲True則分支線程隨主線程退出

設置方法(兩種):

  • t.daenon = True
  • t.setDaemon(True)

判斷屬性值
t.isDaemon()

注意: t.daenon要在start前設置,不能和join同用

多線程代碼實現實例:

from threading import Thread, currentThread
from time import sleep 
import os 

a = 100

#線程函數
def test():
    global a
    a += 10
    # 獲取當前線程的狀態
    print("test is_alive:{}".format(currentThread().is_alive()))
    # 獲取當前線程所在進程的pid
    print("{}:{}".format(currentThread().getName(), os.getpid()))

# 用來測試daemon屬性的
def test3():
	print("進入線程test3...")
	# 阻塞等待10秒
	sleep(10)
	print("我是線程test3!")

#創建線程對象
t1 = Thread(name = "th1", target = test)
t2 = Thread(name = "th2", target = test)
t3 = Thread(target = test3)
t1.start()
t2.start()

# 設置t3線程隨主線程退出而退出
t3.setDaemon(True) 
t3.start()

sleep(2)

# 主線程所在進程pid
print("main-thread:{}".format(os.getpid()))

# 修改線程名稱
t1.setName("new-th1")
print("t1-new-name:"+t1.getName())

# 查看線程狀態
print("t1 is_alive:{}".format(t1.is_alive()))
print("t2 is_alive:{}".format(t2.is_alive()))

# 只需要回收t1和t2
t1.join()
t2.join()

print("a = {}".format(a))

運行結果:

gk@gk-vm:~/python/multithreading$ python3 thread_test.py 
test is_alive:True
th1:9233
test is_alive:True
th2:9233
進入線程test3...
main-thread:9233
t1-new-name:new-th1
t1 is_alive:False
t2 is_alive:False
a = 120

在這個實例中,一個主線程創建了三個子線程(t3是用來測試daemon屬性的),發現可以通過子線程修改主線程中的全局變量a。同時我們發現,主線程和子線程的pid都是一樣的,這說明,他們共用一個進程,即:一個進程中包含了多個線程。再看看daemon屬性,t3設置daemon爲True,我們發現,主線程執行完後,t3線程並沒有執行完就退出了。

線程通信

  • 通信方法:多個線程共享進程的空間,所以線程間通信可以使用全局變量完成(比如上述實例中的a變量)。
  • 注意事項:線程間使用全局變量往往要同步互斥機制保證通信安全

重要!python線程的GIL問題(全局解釋器鎖)

  • 後果:一個解釋器同一時刻只能解釋執行一個線程,所以導致python線程效率低下。但是當遇到IO阻塞時線程會主動讓出解釋器,因此python線程更加適合高延遲的IO程序併發。

解決方法:

  • 若需要實現並行操作,儘量使用多進程
  • 儘量使用多種方案組合的方式進行併發操作,線程用作高延遲IO
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章