[英]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.