2017-10-12 87 views
1

的不同的結果,我寫非常簡單的代碼:使用線程和進程

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 =百萬

N =百萬

它應該是。當我在主要更改代碼,這種情況下:

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,但是我無法理解爲什麼結果總是不同的....?

希望我解釋它透明,你會幫助..

謝謝你提前!

P.S.

最重要的! 以及爲什麼它不是2 000 000?

結果應該是1 000 000 + 1 000 000 = 2 000 000

+1

所有線程共享相同的全局變量。 – Barmar

回答

2

你的線程同時更新n,不一定看到來自其他線程的更新。例如,完全同時更新1的值n。取而代之的3n值只上升到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綁定的代碼。因此,鎖定整個循環會消除線程之間的大量切換和強制。