我得到了一个简单的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()
这里演示了一个经典的并发问题。两个写入程序同时执行操作,因此可能会覆盖另一个写入的数据。在
如果收到13,则线程
A
在线程B
写入结果之前读取,而A
在B
写入结果之后写入。在如果收到14,则线程
B
在线程A
写入结果之前读取,而B
在A
写入结果之后写入。在如果收到15,则一个线程在另一个线程写入结果后读取(并计算和写入)。两个线程的顺序无法确定。在
然而,更有趣的问题是,为什么锁机制(
lockx
/unlockx
)显然不起作用。如果行得通的话,你总可以得到15分。在你的函数名似乎暗示了它们在执行锁定,而事实并非如此。这有两个原因:
key
的访问不保证原子性。在key
的时间和它的值是True
的时间和它被使用并设置为False
之间也存在竞争。在结果,您的两个线程最终以不同步的方式修改共享(在本例中为全局)状态。因此,以下三种情况都有可能:
x
只递增1-B
在A
读取x
之后,但在将递增的值存储回之前,已完全执行。在x
只增加了2—与上面相同的场景中A
和B
相反。在x
分别递增3-A
或{B
或{要正确同步两个线程,必须使用锁定。以下是使用线程提供的工具对代码进行的改编:
可能发生三种不同的情况:
线程A和B在更改之前读取
x
,然后线程A写入结果(13),然后
线程B写入结果(14),
第二个写线程赢了。
线程A或B首先读取
x
,然后和在另一个线程读取之前写入。结果:15,因为A读12,加一写13,然后B读13写15,反之亦然。相关问题 更多 >
编程相关推荐