簡體   English   中英

奇怪的python線程輸出

[英]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的時間之間也存在競爭。

結果,您的兩個線程最終以不同步的方式修改了共享(在這種情況下為全局)狀態。 因此,可能出現以下三種情況:

  1. x僅增加1-在A讀取x之后但在回存增加的值之前, B已完全執行。
  2. x僅增加2-與上述相同的情況,其中AB反。
  3. x遞增3- AB分別在BA之前完全執行。

若要正確同步兩個線程,必須使用鎖定。 這是使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM