[英]Strange python threading output
我得到了一個簡單的python程序進行分析。 它工作正常,並隨機輸出13、14和15(當然)。 我可以看到為什么打印13和14,但是我不知道15的來源。
請解釋。
from threading import Thread
import random
import time
import sys
def rwait():
amt = random.uniform(0.01,0.1)
time.sleep(amt)
x = 0
key = True
def lockx():
global key
while not key:
time.sleep(0)
rwait()
key = False
def unlockx():
global key
key = True
def A():
global x
rwait()
lockx()
reg = x
reg = reg+1
rwait()
x = reg
unlockx()
def B():
global x
rwait()
lockx()
reg = x
reg = reg+2
rwait()
x = reg
unlockx()
def main():
global x
x = 12
p1 = Thread(target=B)
p1.start()
A()
p1.join()
print("x=",x)
for k in range(20):
main()
可能發生三種不同的情況:
線程A和B 在更改之前先讀取x
,然后
線程A寫入其結果(13),並且
線程B寫入其結果(14),
第二個寫勝利的線程。
螺紋A或B讀取x
第一,另一個線程讀取之前寫入。 結果:15,因為A讀12,加1並寫13,然后B讀13並寫15,反之亦然。
您的函數名稱似乎暗示它們正在執行鎖定,而實際上並非如此。 這有兩個原因:
key
訪問原子性。 key
和它的值為True
以及使用它並將其設置為False
的時間之間也存在競爭。 結果,您的兩個線程最終以不同步的方式修改了共享(在這種情況下為全局)狀態。 因此,可能出現以下三種情況:
x
僅增加1-在A
讀取x
之后但在回存增加的值之前, B
已完全執行。 x
僅增加2-與上述相同的情況,其中A
和B
反。 x
遞增3- A
或B
分別在B
或A
之前完全執行。 若要正確同步兩個線程,必須使用鎖定。 這是使用Threading提供的功能對代碼進行的改編:
from threading import Thread, Lock
x = 0
lock = Lock()
def lockx():
global lock
lock.acquire()
def unlockx():
global lock
lock.release()
def A():
global x
lockx()
reg = x
reg = reg+1
x = reg
unlockx()
def B():
global x
lockx()
reg = x
reg = reg+2
x = reg
unlockx()
def main():
global x
x = 12
p1 = Thread(target=B)
p1.start()
A()
p1.join()
print("x=",x)
for k in range(20):
main()
您已在此處演示了經典的並發問題。 兩位作家同時行動,因此有可能覆蓋另一位作家所寫的數據。
如果收到13,則線程A
在線程B
寫入結果之前讀取,而A
在 B
寫入結果之后寫入。
如果收到14,則線程B
在線程A
寫入結果之前讀取,而B
在 A
寫入結果之后寫入。
如果收到15,則一個線程在另一線程寫入結果后讀取(並計算和寫入)。 然后無法確定兩個線程的順序。
然而,更有趣的問題是,為什么鎖定機制( lockx
/ unlockx
)顯然不起作用。 它將起作用,結果您總是得到15。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.