1. 程式人生 > 其它 >記錄---python執行緒和鎖

記錄---python執行緒和鎖

1、threading模組介紹 python的thread模組是比較底層的模組,python的threading模組是對thread做了一些包裝的,可以更加方便的被使用
  • 建立執行緒物件:threading.Thread(target=func)
  • 引數target指定執行緒執行的任務 (函式)
Thread類提供了以下方法:
  • run():用以表示執行緒活動的方法
  • start():啟動執行緒活動
  • join([time]):設定主執行緒會等待time秒後再往下執行,time預設為子執行緒結束,多個子執行緒之間設定的值會疊加
import time

def func1(name):
for i in range(5):
print("{}------正在做事情1------".format(name))
time.sleep(1)
# 執行緒切換

def func2(name):
for i in range(6):
print("{}-----正在做事情2------".format(name))
time.sleep(1)

"""
建立執行緒的引數:
target:指定執行緒執行的任務函式
name:設定執行緒名稱
args:給任務函式傳遞引數(元組)
kwargs:給任務函式傳遞引數(字典)
daemon:是否設為守護執行緒
守護執行緒:主執行緒執行結束、子執行緒不管有沒有執行完,都終止執行

執行緒物件的方法:
start():啟動執行緒
join():設定主執行緒等待子執行緒執行的時間(預設等待執行完)
getName() # 獲取執行緒名
is_alive() # 判斷執行緒是否存活
isAlive()
isDaemon() # 判斷是否為守護執行緒

python中執行緒釋放全域性直譯器鎖的兩種狀態(執行緒切換):
1、執行緒中執行遇到IO、耗時操作
2、執行緒執行的時達到指定的閾值(0.005秒)
# 獲取執行緒切換的閾值
# import sys
# print(sys.getswitchinterval())

"""

# 多工模式(多執行緒、多程序、協程去實現)
from threading import Thread

# 建立一個執行緒物件
t = Thread(target=func1, name='z1', args=('zyj1',))
t2 = Thread(target=func2, name='z2', kwargs={'name': "zyj2"})

# 獲取執行緒名:
# print(t.getName())
# print(t2.getName())

# 啟動執行緒執行
st = time.time()
t.start()
t2.start()

# 設定主執行緒等待子執行緒執行結束
t.join()
t2.join()

# 其他的方法
et = time.time()
print("執行時間為:", et - st)
多執行緒-共享全域性變數 1、多執行緒之間修改全域性變數
  • 執行緒之間是共用同一塊記憶體的,那麼執行緒可以共享全域性變數
    • 案例:當前有一個全域性變數 a=100, 再執行緒a中修改,執行緒b中是否會生效。
    • 列表當做實參傳遞到執行緒中,執行緒中修改會有說明影響 
  • 總結
    • 在一個程序內的所有執行緒共享全域性變數,很方便在多個執行緒間共享資料** 
    • 缺點就是,執行緒是對全域性變數隨意遂改可能造成多執行緒之間對全域性變數的混亂(即執行緒非安 全
2、多執行緒-共享全域性變數的問題 如果多個執行緒同時對同一個全域性變數操作,會出現資源競爭問題,從而資料結果會不正確 鎖-Lock
  • 上面的bug如何解決?控制執行緒的執行,避免同時獲取資料
  • 執行緒同步能夠保證多個執行緒安全訪問競爭資源,最簡單的同步機制是引⼊互斥鎖。
  • 互斥鎖為資源引⼊⼀個狀態:鎖定/⾮鎖定。
  • 某個執行緒要更改共享資料時,先將其鎖定,此時資源的狀態為“鎖定”,其他執行緒不能更改直到該線
  • 程釋放資源,將資源的狀態變成“⾮鎖定”,其他的執行緒才能再次鎖定該資源
  • 互斥鎖保證了每次只有⼀個執行緒進⾏寫⼊操作,從⽽保證了多執行緒情況下資料的正確性
  • threading模組中定義了Lock類,可以方便的處理鎖定
# 建立鎖 
mutex = threading.Lock()
# 鎖定
mutex.acquire()
# 釋放
mutex.release()
注意: 如果這個鎖之前是沒有上鎖的,那麼acquire不會堵塞 如果在呼叫acquire對這個鎖上鎖之前 它已經被 其他執行緒上了鎖,那麼此時acquire會堵塞,直到這個鎖被解鎖為止 
  • 上鎖解鎖過程
    • 當一個執行緒呼叫鎖的acquire()方法獲得鎖時,鎖就進入“locked”狀態
    • 每次只有一個執行緒可以獲得鎖。如果此時另一個執行緒試圖獲得這個鎖,該執行緒就會變為“blocked”狀態,稱為“阻塞”,直到擁有鎖的執行緒呼叫鎖的release()方法釋放鎖之後,鎖進入“unlocked”狀態
    • 執行緒排程程式從處於同步阻塞狀態的執行緒中選擇一個來獲得鎖,並使得該執行緒進入執行(running)狀態
  • 總結
    • 鎖的好處:確保了某段關鍵程式碼只能由一個執行緒從頭到尾完整地執行
    • 鎖的壞處:
      • 阻止了多執行緒併發執行,包含鎖的某段程式碼實際上只能以單執行緒模式執行,效率就大大地下降了
      • 由於可以存在多個鎖,不同的執行緒持有不同的鎖,並試圖獲取對方持有的鎖時,可能會造成死鎖