繁体   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