[英]How do I increase variable value when multithreading in python
我正在嘗試使用多線程制作網絡爬蟲以使其更快。 我想讓每次執行都增加價值。 但有時該值會自行跳過或重復。
import threading
num = 0
def scan():
while True:
global num
num += 1
print(num)
open('logs.txt','a').write(str(f'{num}\n'))
for x in range(500):
threading.Thread(target=scan).start()
結果:
2
2
5
5
7
8
10
10
12
13
13
13
16
17
19
19
22
23
24
25
26
28
29
29
31
32
33
34
預期結果:
1
2
3
4
5
6
7
8
9
10
因此,由於變量num
是共享資源,因此您需要對其進行鎖定。 這是按如下方式完成的:
num_lock = threading.Lock()
每次要更新共享變量時,都需要線程先獲取鎖。 一旦獲得了鎖,只有該線程可以訪問更新 num 的值,而當當前線程獲得鎖時,沒有其他線程能夠這樣做。
確保在執行此操作時使用wait
或try-finally
塊,以保證即使當前線程未能更新共享變量,也會釋放鎖。
像這樣的東西:
num_lock.acquire()
try:
num+=1
finally:
num_lock.release()
使用with
:
with num_lock:
num+=1
似乎是一種競爭條件。 您可以使用鎖,以便只有一個線程可以獲得特定編號。 使用鎖寫入輸出文件也是有意義的。
這是一個帶鎖的例子。 當然,您不能保證寫入輸出的順序,但每個項目都應該只寫入一次。 在此示例中,我添加了 10000 的限制,以便您可以更輕松地檢查所有內容是否最終都寫入測試代碼中,否則無論何時中斷它,都很難驗證某個數字是被跳過還是只是在等待用於寫輸出的鎖。
該my_num
不共享,那么你已經聲明它里面后with num_lock
部分,你可以自由地釋放鎖(保護共享num
),然后繼續使用my_num
在外面with
其他線程可以訪問鎖定以索取自己的價值。 這最大限度地減少了持有鎖的持續時間。
import threading
num = 0
num_lock = threading.Lock()
file_lock = threading.Lock()
def scan():
global num_lock, file_lock, num
while num < 10000:
with num_lock:
num += 1
my_num = num
# do whatever you want here using my_num
# but do not touch num
with file_lock:
open('logs.txt','a').write(str(f'{my_num}\n'))
threads = [threading.Thread(target=scan) for _ in range(500)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
除了threading.Lock
之外還有一個重要的標注:
join
使父線程等待分叉線程完成。 假設我在線程完成后使用num
:
import threading
lock, num = threading.Lock(), 0
def operation():
global num
print("Operation has started")
with lock:
num += 1
threads = [threading.Thread(target=operation) for x in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()
print(num)
沒有連接,不一致(9 打印一次,否則 10):
Operation has started
Operation has started
Operation has started
Operation has started
Operation has startedOperation has started
Operation has started
Operation has started
Operation has started
Operation has started9
使用 join,其一致:
Operation has started
Operation has started
Operation has started
Operation has started
Operation has started
Operation has started
Operation has started
Operation has started
Operation has started
Operation has started
10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.