Ich versuche, Django 1.6 Transaktionen zu verwenden, um Race Conditions auf einem Spiel zu vermeiden, das ich entwickle. Der Spielserver hat ein einfaches Ziel: zwei Spieler zu paaren.Django 1.6 Transaktionen, um Race Conditions zu vermeiden
Mein aktueller Ansatz ist:
- Benutzer will
- prüft der Server spielen, wenn es jemand wartet anderes zu spielen.
- Wenn dort nicht ist, wird ein GameConnection-Objekt erstellt (das eine eindeutige ID hat - uuid4).
- Wenn ist, erhält es die GameConnection-Kennung und löscht die GameConnection.
Dies ist der Code:
# 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
Offensichtlich gibt es eine Race-Bedingung oben auf dem Code. Da dieser Code nicht atomar ist, kann es passieren, dass:
- A überprüft für Spiele-Verbindungen. Findet keine.
- A erstellt eine Spielverbindung.
- B prüft auf Spielverbindungen. Findet einen (A).
- C sucht nach Spielverbindungen. Findet einen (A).
- B erhält die Verbindungskennung A und startet ein Spiel.
- C erhält die Verbindungskennung von A und startet ein Spiel.
Ich habe versucht, sie aber diese ganze Block unter with transaction.atomic():
oder den @transaction.atomic
Dekorateur zu verwenden. Trotzdem kann ich die Race Condition reproduzieren.
Ich bin sicher, da ist etwas über die Transaktionsdynamik, die ich hier vermisse. Kann jemand Licht werfen?
Ich bin kein Experte, aber nach meinem Verständnis gelten die atomaren Transaktionen für Schreibvorgänge. In Ihrem Fall möchten Sie möglicherweise eine Art von Mutex-Sperren verwenden, um sicherzustellen, dass jeweils nur eine Paarung stattfindet. Dies ist vergleichbar mit @synchronized in Java. Allerdings nicht leistungsfähig. –