Ale*_*lho 7 python django multithreading transactions race-condition
我正在尝试使用Django 1.6交易来避免我正在开发的游戏中的竞争条件.游戏服务器有一个简单的目标:配对两个玩家.
我目前的做法是:
这是代码:
# data['nickname'] = user's choice
games = GameConnection.objects.all()
if not games:
game = GameConnection.objects.create(connection=unicode(uuid.uuid4()))
game.nick1 = data["nickname"]
game.save()
response = HttpResponse(json.dumps({'connectionId': game.connection, 'whoAmI': 1, 'nick1': game.nick1, 'nick2': ""}))
else:
game = games[0]
conn = game.connection
nick1 = game.nick1
nick2 = data["nickname"]
game.delete()
response = HttpResponse(json.dumps({'connectionId': conn, 'whoAmI': 2, 'nick1': nick1, 'nick2': nick2}))
return response
Run Code Online (Sandbox Code Playgroud)
显然上面的代码存在竞争条件.由于此代码不是原子的,因此可能会发生:
我试过但是整个块下面with transaction.atomic():
,或者使用@transaction.atomic
装饰器.但是,我仍然可以重现竞争条件.
我相信我在这里缺少一些交易动态.任何人都可以光明吗?
@Sai 正在步入正轨......关键是锁定/互斥体在写入(或删除)之前不会发生。按照编码,在挂起连接的“发现”(读取)和挂起连接的“声明”(写入/锁定)之间始终存在一段时间,无法知道连接是否正在声明过程中。
如果您使用 PostgreSQL(很确定 MySQL 也支持它),您可以使用“select for update”强制锁定,这将阻止另一个请求获取同一行,直到事务完成:
game = GameConnection.objects.all()[:1].select_for_update()
if game:
#do something, update, delete, etc.
else:
#create
Run Code Online (Sandbox Code Playgroud)
最后注意事项 - 除了all()
明确说明可能会选择哪个游戏(例如,按“创建”时间戳或其他内容排序)之外,请考虑其他事项。希望有帮助。
归档时间: |
|
查看次数: |
579 次 |
最近记录: |