奇怪的python线程输出

2024-06-07 18:44:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我得到了一个简单的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()

Tags: keyimporttruetimedefsleeprandomreg
3条回答

这里演示了一个经典的并发问题。两个写入程序同时执行操作,因此可能会覆盖另一个写入的数据。在

如果收到13,则线程A在线程B写入结果之前读取,而AB写入结果之后写入。在

如果收到14,则线程B线程A写入结果之前读取,而BA写入结果之后写入。在

如果收到15,则一个线程在另一个线程写入结果后读取(并计算和写入)。两个线程的顺序无法确定。在

然而,更有趣的问题是,为什么锁机制(lockx/unlockx)显然不起作用。如果行得通的话,你总可以得到15分。在

你的函数名似乎暗示了它们在执行锁定,而事实并非如此。这有两个原因:

  • key的访问不保证原子性。在
  • 即使是这样,在读取key的时间和它的值是True的时间和它被使用并设置为False之间也存在竞争。在

结果,您的两个线程最终以不同步的方式修改共享(在本例中为全局)状态。因此,以下三种情况都有可能:

  1. x只递增1-BA读取x之后,但在将递增的值存储回之前,已完全执行。在
  2. x只增加了2—与上面相同的场景中AB相反。在
  3. x分别递增3-A或{}在B或{}之前完全执行。在

要正确同步两个线程,必须使用锁定。以下是使用线程提供的工具对代码进行的改编:

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()

可能发生三种不同的情况:

  • 线程A和B在更改之前读取x,然后

    • 线程A写入结果(13),然后

    • 线程B写入结果(14),

    第二个写线程赢了。

  • 线程A或B首先读取x,然后在另一个线程读取之前写入。结果:15,因为A读12,加一写13,然后B读13写15,反之亦然。

相关问题 更多 >

    热门问题