1.在多線程中,不可避免的一個問題,就是全局變量資源存在着被多個線程調用的問題,在調用的過程中就存在着資源競爭
2.這種資源競爭是如何產生的呢?
import threading
import time
g_num = 0
def work1(num):
global g_num
for i in range(num):
g_num += 1
print("----in work1, g_num is %d---"%g_num)
def work2(num):
global g_num
for i in range(num):
g_num += 1
print("----in work2, g_num is %d---"%g_num)
print("---線程創建之前g_num is %d---"%g_num)
t1 = threading.Thread(target=work1, args=(100,))
t1.start()
t2 = threading.Thread(target=work2, args=(100,))
t2.start()
while len(threading.enumerate()) != 1:
time.sleep(1)
print("2個線程對同一個全局變量操作之后的最終結果是:%s" % g_num)
如同上述代碼,當線程執行次數有限時,全局資源不會發生大的變化,但是當高並發時,就會產生資源競爭問題,如以下代碼:
import threading import time g_num = 0 def work1(num): global g_num for i in range(num): g_num += 1 print("----in work1, g_num is %d---"%g_num) def work2(num): global g_num for i in range(num): g_num += 1 print("----in work2, g_num is %d---"%g_num) print("---線程創建之前g_num is %d---"%g_num) t1 = threading.Thread(target=work1, args=(1000000,)) t1.start() t2 = threading.Thread(target=work2, args=(1000000,)) t2.start() while len(threading.enumerate()) != 1: time.sleep(1) print("2個線程對同一個全局變量操作之后的最終結果是:%s" % g_num)
3.如何解決資源競爭問題?
當存在多個線程或者進程同時調用一個全局變量資源,並且會對它進行修改時,可以采用上鎖這個方法,來解決資源競爭問題。
首先,需要了解什么叫做資源競爭?
資源競爭是指,一個全局變量資源在多個線程或者進程中被同時調用,造成該全局變量資源不斷的被修改。
解決方法:采用全局變量鎖,每當線程調用全局變量時,就將該資源上鎖,不允許被調用,只有當調用結束后才打開鎖,這里引入互斥鎖,能夠保證全局變量資源的安全。
互斥鎖的兩種狀態:鎖定/非鎖定
解決資源競爭的好處:互斥鎖保證了每次只有一個線程進行寫入操作,從而保證了多線程情況下數據的正確性。
4.互斥鎖的定義
當在請求之前,資源沒有被上鎖,那么請求並不會堵塞;如果在請求之前,是被鎖上的, 那么請求就處於一個堵塞狀態,只有當前得鎖被打開之后,才能在次上鎖。
互斥鎖的優缺點:
優點:確保了某段關鍵代碼只能由一個線程從頭到尾完整地執行
缺點:阻止了多線程並發執行,包含鎖的某段代碼實際上只能以單線程模式執行,效率就大大地下降了
由於可以存在多個鎖,不同的線程持有不同的鎖,並試圖獲取對方持有的鎖時,可能會造成死鎖
# 創建鎖 mutex = threading.Lock() # 鎖定 mutex.acquire() # 釋放 mutex.release()
