2011-12-13 13 views
5

Ho un server Web in esecuzione in Python. Il server è privato, quindi mi aspetto solo circa 20 utenti per connettersi ad esso. Il server è multi-threaded (8 core al momento, quindi 8 thread ho indovinato).Come si può rendere sicuro questo thread di Python Dictionary?

Quando le richieste sono disponibili in, sono in grado di identificare gli utenti. In alcune query, è necessario aggiornare un semplice dictionary del nome utente -> Boolean. Come posso rendere sicuro questo thread?

+0

Stai implementando tu stesso il server o stai usando qualcosa come django, piramide o twistato? – dirk

+0

È cherrypy, versione 3.2 – Jerome

risposta

5

Se avete bisogno di una serratura (per evitare le condizioni di gara Joonas descritto), e sono bloccati con Python 2.4,

import threading 
lock = threading.Lock() 

shared_dict = {} 

def do_thing(user, value): 
    lock.acquire() 
    try: 
     shared_dict[user] = value 
    finally: 
     # Always called, even if exception is raised in try block 
     lock.release() 
+0

diciamo che il mio scrittore avvolge le sue modifiche sotto quel blocco. Il lettore aspetterà che venga rilasciato, cioè che la scrittura sia finita? O ho bisogno di avvolgere le letture anche in questo? – Jerome

+0

@jeromeG probabilmente dovresti avere una funzione bloccata simile per la lettura (di nuovo solo per evitare le condizioni di gara "leggi-modifica-scrittura") – dbr

2

Usa threading.LOCK.acquire() prima di aggiornare il dizionario e usare threading.LOCK.release(), una volta che si è fatto l'aggiornamento di esso.

+0

Questo è strano, mi sarei aspettato l'oggetto di blocco per essere precisi al dizionario, un po 'come un oggetto/blocco/metodo sincronizzato in Java ... sono confusa – Jerome

8

Avrai bisogno di creare un oggetto blocco globale.

lock = threading.Lock() 

Quindi attorno ad ogni accesso del dizionario acquisire e rilasciare il blocco. Il modo più semplice per farlo è con il nuovo (ish) with syntax.

with lock: 
    dict[key] = value 
+0

mi sono limitato a l'uso di Python 2.4, non sarebbe disponibile? – Jerome

+0

No, il con non è disponibile, ma puoi usare lock.acquire() e lock.release(). –

4

Si può o non può essere necessario utilizzare un blocco, a seconda di come la Boolean viene aggiornato.

Se il valore della Booleannon si dipende dal suo valore precedente, quindi è necessario nessun blocco: la scrittura e la lettura di un dizionario Python è thread-safe di per sé (ad eccezione di: writing while iterating is not allowed - ma che non è permesso in single filo o). La visibilità della memoria è simile a quella che si otterrebbe utilizzando volatile in alcune lingue.

Che cosa non è intrinsecamente thread-safe è il -sequence "lettura-modifica-scrittura", con conseguente una condizione di competizione. Se il valore della Booleanfa dipende dal suo valore precedente, quindi è necessario utilizzare un blocco, perché altrimenti infilare un poteva leggere prima il valore, quindi filo B potrebbe cambiare, e poi un aspirante cambiare di nuovo, sulla base di valore obsoleto per iniziare.

0

Non è necessaria per bloccare dizionario a questa operazione, perché questa operazione è atomica e GIL ti prendi cura di te. A meno che tu non abbia operazioni come read-change-write, non ti preoccupare.

Problemi correlati