使用Thread和Process的结果不同

时间:2017-10-12 18:18:26

标签: python multithreading

我编写了非常简单的代码:

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.

当我们在Threads中执行它时,它们以某种方式分割全局变量n,但是我无法理解为什么结果总是不同的东西......?

希望我确实解释它透明,你会帮助..

提前谢谢!

P.S。

最重要的! 为什么不是2 000 000?

结果应为1 000 000 + 1 000 000 = 2 000 000

1 个答案:

答案 0 :(得分:2)

您的主题同时更新n,并且不一定会看到来自其他主题的更新。例如,两者都在同一时间更新值n的{​​{1}}。 1的值3仅增加到n而不是2。这种情况多次发生。因此,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绑定代码。 因此,锁定整个循环会消除线程之间的大量切换和强制。