2011-04-19 94 views
1

我對Python很陌生,我正在研究一個多處理示例腳本。代碼大約100行,所以你可以在這裏找到它 - http://pastie.org/1813365進程間數據共享的問題

這是一個簡單的遊戲,發生在方形領域 - 他們被表示爲矩陣(列表包含x個x元素嵌套列表每個)。爲每個玩家創建一個單獨的遊戲區域。

我創建的每個過程都代表一個玩家。每輪和每個「玩家」,兩個座標和一個數字(0-9)生成(隨機)。每個「玩家」試圖將他的數字放在場地的座標上;如果在這些座標中的其他玩家的場地上沒有數字,或者這個數字小於第一個玩家的數字,或者如果第一個玩家有'0'(它就像'百搭卡') - 數字是(當然,應該是)放在兩個場上,並且球員的得分會增加。遊戲在指定次數的迭代後結束。

所有數據都存儲在包含數據的類的單個對象中,該對象正在從主線程傳輸到「第一個玩家」線程,然後不斷從一個線程傳輸到另一個線程,來回傳輸,直到比賽結束。 'JoinableQueue'正在被使用。

關於代碼的問題是,似乎每個「玩家」都有自己的兩個遊戲領域的副本。如果您每回合都從雙方都輸出兩個遊戲領域,您可以清楚地看到這一點 - 他們對於每個玩家都是相同的。例如,註釋行沒有任何影響,因爲其他玩家(正在打印在輪到他)字段絕不會被修改:

if x.data_PC[y2][x2] == 'X' or z2 == 0 or int(x.data_PC[y2][x2]) < z2:   
    x.data_PC2[y2][x2] = str(z2) # doesn't work 
    x.data_PC[y2][x2] = str(z2) 
    x.score_PC2 += 1 

這是因爲在對象中的所有剩餘的數據尤其是陌生的似乎是工作得很好。

是什麼導致了這種行爲,我該如何解決這個問題?

+0

爲什麼你首先使用多處理?面向對象的方法會使你的生活縮短很多。不僅如此......爲什麼你甚至會使用多處理來模擬由此導致的並且不是併發的回合制遊戲? – ktdrv 2011-04-19 22:54:22

+0

因爲我需要創建一個使用多處理(或至少是多線程)的程序。實際上,對於學術貴族來說。這些條件(基於回合的遊戲,「爲了遊戲領域的資源而戰」等等)不是由我發明的。 :) – havelock 2011-04-19 22:57:01

+0

我可能會將遊戲數據作爲共享狀態,並用鎖來控制轉動。這似乎比將遊戲狀態在隊列中來回傳遞更簡單。 http://docs.python.org/library/multiprocessing。html#sharing-state-between-processes – 2011-04-19 23:14:03

回答

2

好的,你的問題與多處理沒有任何關係。如果你看你的data類定義(你應該大寫你的類名,這是pythonic那樣),你創建的所有變量都是類變量。您希望它們處於__init__方法中,並將其定義爲self.foo=1,以便它們是實例變量並可在進程之間傳遞。像這樣:

class Data(object): 

    def __init__(self): 

     self.SIZE = 8 # dimensions of the game field 
     self.MAX_TURNS = 5 # amount of iterations for each of the players ("turns") before the end 
     self.turns = 0 # count of turns done 
     self.score_PC = self.score_PC2 = 0 # score values 

     # create and init the data matrices 
     self.data_PC = [['X' for j in xrange(self.SIZE)] for i in xrange(self.SIZE)] 
     self.data_PC2 = [['X' for j in xrange(self.SIZE)] for i in xrange(self.SIZE)] 

現在談談多處理方面的一些話。如果您使用可連接隊列,則不需要鎖定。所有你需要做的是.get()的數據,處理它和.put()它回到隊列中,並讓它知道.task_done()。它會考慮併發性。我發貼your code with the needed edits

+0

謝謝。現在看來我明白這一點。沒有隊列連接的代碼工作得很好,但是有一個小問題 - 有時是在腳本完成之後隨機的,「線程QueueFeederThread中的異常(最有可能在解釋器關閉期間引發):'彈出(CPython 2.7.1 ,Win7 x64)。據我記得,除非我引入隊列連接,否則這也發生在我的原始代碼中。鎖只是我之前嘗試過的方法,但沒有成功 - 如上所述,以共享狀態存儲數據。當我有足夠的聲望時,我會投票回答答案。 – havelock 2011-04-20 18:37:05

+0

是的,還有最後一件事 - 就我從文檔中得到它而言,似乎'.task_done()'用於'.put()'數據放在隊列中,然後'.get()'並處理它。我的意思是,'.task_done()'在'.g​​et()'後面使用,而不是在'.put()'之後使用,不是嗎? – havelock 2011-04-20 18:43:40

+0

如果您有興趣,[此修訂版](http://pastie.org/1816530)適用於我,並且沒有任何問題或錯誤信息。 'q.join()'-s可能讓我有點偏執,但我喜歡安全。 – havelock 2011-04-20 19:18:18