Sto provando a utilizzare le transazioni Django 1.6 per evitare le condizioni di gara in un gioco che sto sviluppando. Il server di gioco ha un obiettivo semplice: abbinare due giocatori.Django 1.6 transazioni per evitare condizioni di gara
Il mio approccio attuale è:
- utente vuole giocare
- I server controlla se c'è qualcun altro in attesa di giocare.
- Se c'è non è, si crea un oggetto GameConnection (che ha un identificatore univoco - uuid4).
- Se è, ottiene l'identificatore GameConnection ed elimina la GameConnection.
Questo è il codice:
# 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
Ovviamente c'è una condizione di competizione sul codice di cui sopra. Poiché questo codice non è atomico, può succedere che:
- Un controllo per le connessioni di gioco. Non ne trova.
- A crea una connessione di gioco.
- B controlla le connessioni di gioco. Trova uno (A).
- C controlla le connessioni di gioco. Trova uno (A).
- B ottiene l'identificatore di connessione di A e avvia una partita.
- C ottiene l'identificatore di connessione di A e avvia una partita.
Ho provato fare ma tutto questo blocco sotto with transaction.atomic():
, o per utilizzare la @transaction.atomic
decoratore. Ma ancora, sono in grado di riprodurre le condizioni della gara.
Sono sicuro che c'è qualcosa nella dinamica delle transazioni che mi manca qui. Qualcuno può far luce?
Non sono un esperto, ma secondo la mia comprensione, le transazioni atomiche si applicano per le scritture. Nel tuo caso, potresti voler utilizzare qualche tipo di blocco mutex per garantire che avvenga un solo accoppiamento alla volta. Questo è simile a @synchronized in Java. Però non è efficiente a tutti i livelli di rendimento. –