tastype文档声明绑定keep Tastypie more thread-safe,但没有解释如何以及在什么条件下。我已经看过了code,但是经验不足,没有足够的经验来围着它转。在
我正在制作一个游戏的原型,它有一个圆形对象(对于每一轮游戏)和每轮的多个状态(对于每一轮的每个玩家的信息)。每个玩家都会更新自己的状态,并给出回合词短语的答案。我需要一种机制,如果还不存在的话,它会懒洋洋地创造下一轮比赛。当玩家更新他们的状态时,我会触发这个回合的创建。在
如果多个玩家同时更新他们的状态(见StateResource.obj_update()
),那么他们试图制造下一轮的碰撞会不会发生?我认为如果一个obj_update
调用检查下一轮是否存在,并在另一个obj_update
完成下一轮创建之前尝试创建下一轮,则可能会发生这种情况。我会用某种类型的互斥来解决这个问题,但我不确定是否有必要。我想知道是否有一个典型的方法来解决这个问题。在
我的代码如下:
#models.py
class Round(models.Model):
game_uid = models.CharField(max_length=75)
word = models.CharField(max_length=75)
players = models.ManyToManyField(User)
next_round = models.OneToOneField('self',null=True,blank=True)
class PlayerRoundState(models.Model):
player = models.ForeignKey(User)
round = models.ForeignKey(Round)
answer = models.CharField(max_length=75)
#api.py
class RoundResource(ModelResource):
players = fields.ManyToManyField(UserResource, attribute='players',full=False)
states = fields.ManyToManyField('wordgame.api.StateResource',
attribute='playerroundstate_set',
full=True)
. . .
def obj_create(self, bundle, request=None, **kwargs):
bundle = super(RoundResource, self).obj_create(bundle, request,**kwargs)
bundle.obj.word = choice(words) #Gets a random word from a list
bundle.obj.round_number = 1
bundle.obj.game_uid = bundle.obj.calc_guid() #Creates a unique ID for the game
bundle.obj.save()
return bundle
class StateResource(ModelResource):
player = fields.ForeignKey(UserResource, 'player',full=False)
round = fields.ForeignKey(RoundResource, 'round')
. . .
def obj_update(self, bundle, request=None, skip_errors=False, **kwargs):
bundle = super(StateResource, self).obj_update(bundle, request,
skip_errors, **kwargs)
if bundle.obj.round.next_round is None:
new_round = Round()
new_round.word = choice(words)
new_round.round_number = bundle.obj.round.round_number + 1
new_round.game_uid = bundle.obj.round.game_uid
new_round.save()
for p in bundle.obj.round.players.all():
new_round.players.add(p)
new_round.save()
bundle.obj.round.next_round = new_round
bundle.obj.round.save()
return bundle
我觉得这跟品味没什么关系。在
您所描述的问题与ORM和数据库有关。{gen}在某些情况下,{grn>在一个新的情况下,都可以创建一个新的请求,如果在这个情况下,^都是新的,那么这两个请求都可能在一个时间内被处理。在
考虑以下情况:
第一个请求到达,检索当前轮并“看到”没有“下一轮”。所以它表现为:
同时,第二个请求来了(假设在您的设置中是可能的)处理切换到第二个请求。它还检索当前轮,并且“看到”没有下一轮,因此它也创建了一个(同一逻辑轮的第二个对象)。在
然后,处理切换回执行以下操作的第一个请求:
^{pr2}$所以现在有了下一轮。第一个请求被处理,一切看起来都很好。 但是第二个请求还没有完成,它执行同样的操作,覆盖当前的round对象。在
结果是您有一个过时的实例(由第一个请求创建的
Round
),并且第一组玩家使用与第二组不同的Round
。在这会导致数据库中的状态不一致。所以在这种情况下,您的资源更新方法是线程安全的。在
一种解决方案是使用
select_for_update
从数据库中检索当前回合。见Django Docs。如果使用该方法,则第二个和连续的请求将一直等到您在第一个请求中修改当前轮,然后才从数据库中检索它。结果将是,他们已经“看到”下一轮,而不是试图创造它。当然,您必须确保整个更新构成一个事务。在“使用”的方法是重写
StateResource
资源中的obj_get()
方法,而不是:使用(未测试):
当然,这不是唯一的解决方案,但其他解决方案可能会涉及到重新设计应用程序,因此这可能会减少涉及。在
相关问题 更多 >
编程相关推荐