进程间数据共享的问题

进程间数据共享的问题

问题描述:

我对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

好的,你的问题与多处理没有任何关系。如果你看你的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