我写了非常简单的代码:
n = 0
def calculate_n(number):
global n
for i in range(number):
n += 1
print n
def print_n():
global n
print "n= "
print n
在主要部分:
if __name__ == '__main__':
number = 1000000
t1 = Process(target=calculate_n, args=(number,))
t1.start()
t2 = Process(target=calculate_n, args=(number,))
t2.start()
print_n()
它给出了结果:
n = 1000000
n = 1000000
应该如此。当我将 main 中的代码更改为这种情况时:
number = 1000000
t1 = Thread(target=calculate_n, args=(number, ))
t1.start()
t2 = Thread(target=calculate_n, args=(number,))
t2.start()
我总是得到不同的结果:
n = 1388791
n = 1390167
<小时/>n = 1426284
n = 1427452
<小时/>n = 1295707
n = 1297116
<小时/>等等。
所以第一种情况相当简单。当我们执行 Process 时,代码在不同的进程中运行,并且两个不同的进程使用“不同的”全局变量 n,并且我总是得到预期的结果:1000000 和 1000000。
当我们在线程中执行它时,它们以某种方式分割全局变量 n,但我无法理解为什么结果总是不同......?
希望我能解释清楚,你会有所帮助..
提前谢谢您!
附注
最重要的是! 为什么不是 2 000 000?
结果应为 1 000 000 + 1 000 000 = 2 000 000
最佳答案
您的线程同时更新n
,并且不一定会看到来自其他线程的更新。例如,两者完全同时更新值 1
的 n
。 n
的值仅增加到 2
,而不是 3
。这种情况发生多次。因此,n
的值始终小于 2000000。
您需要查看全局变量:
from threading import Thread, RLock
lock = RLock()
n = 0
def calculate_n(number):
global n
for i in range(number):
with lock:
n += 1
print n
def print_n():
global n
print "n= "
print n
if __name__ == '__main__':
number = 1000000
t1 = Thread(target=calculate_n, args=(number, ))
t1.start()
t2 = Thread(target=calculate_n, args=(number,))
t2.start()
t1.join()
t2.join()
print_n()
输出:
1991917
2000000
n=
2000000
这会大大减慢速度。锁定整个循环可以使事情变得更快:
def calculate_n(number):
global n
with lock:
for i in range(number):
n += 1
print n
由于 GIL 线程无论如何都不会加速 CPU 密集型代码。 因此锁定整个循环消除了线程之间的大量切换和强制。
关于python - 使用Thread和Process的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46716388/