2010-02-09 20 views

risposta

39

È necessario implementare il proprio blocco per tutte le variabili condivise che verranno modificate in Python. Non dovete preoccuparvi di lettura dalle variabili che non sarà modificato (vale a dire, in concomitanza letture sono ok), tipi così immutabili (frozenset, tuple, str) sono probabilmente sicuro, ma non sarebbe male. Per le cose che cambierete - list, set, dict e la maggior parte degli altri oggetti, dovreste avere il vostro meccanismo di blocco (mentre le operazioni sul posto sono ok su molti di questi, i thread possono portare a bug super-cattivi - si potrebbe anche implementare il blocco, è piuttosto facile).

A proposito, non so se lo sai, ma di bloccaggio è molto facile in Python - Creare un oggetto threading.lock, e quindi è possibile acquisire/rilasciarlo in questo modo:

import threading 
list1Lock = threading.Lock() 

with list1Lock: 
    # change or read from the list here 
# continue doing other stuff (the lock is released when you leave the with block) 

In Python 2.5, fare from __future__ import with_statement; Python 2.4 e prima che non dispongono di questo, quindi ti consigliamo di mettere l'acquire()/rilascio() chiama in try:...finally: blocchi:

import threading 
list1Lock = threading.Lock() 

try: 
    list1Lock.acquire() 
    # change or read from the list here 
finally: 
    list1Lock.release() 
# continue doing other stuff (the lock is released when you leave the with block) 

Some very good information about thread synchronization in Python.

+12

Credo che, per qualcuno che non ha mai utilizzato i blocchi di threading, si noti che il blocco (nell'esempio, 'list1Lock') deve essere * condiviso * tra i thread, affinché funzioni correttamente. Due chiusure indipendenti, una per ogni filo, non bloccherebbero nulla, aggiungendo semplicemente un overhead sciocco. – tzot

+0

Non dovrebbe essere questo: con list1Lock: # Do stuff –

+0

@ slack3r Good call! –

3

Sono thread-safe purché non si disabiliti GIL in codice C per il thread.

+5

Questo è un dettaglio di implementazione di CPython non si dovrebbe sempre contare su. Probabilmente succederà in futuro e altre implementazioni non ce l'hanno. –

+0

Georg: questo aspetto del genere pitone mi colpisce. Non importa a tutti i bug che abbandoneranno i programmi java quando 8 core diventeranno comuni sul desktop - cosa succede quando GIL viene rimosso e le applicazioni python multithread sono improvvisamente in esecuzione su 8 core box? – Ben

+3

Non dovrebbe terrorizzare nessuno se non pretende che il loro codice sia sicuro per i thread quando non lo è. :) – Kylotan

7

Sì, ma è ancora necessario fare attenzione, naturalmente

Ad esempio:

Se due thread fanno a gara per pop() da un elenco con una sola voce, un thread otterrà la voce con successo e la altri avranno un IndexError

codice come questo non è thread-safe

if L: 
    item=L.pop() # L might be empty by the time this line gets executed 

si dovrebbe WR ite come questo

try: 
    item=L.pop() 
except IndexError: 
    # No items left 
+5

Voglio pop() per essere protetto da thread, ma non riesco a trovare questo fatto da nessuna parte nella documentazione. Qualcuno può aiutarmi a trovare questa affermazione prima di prenderla come vangelo? –

+0

Davvero? list.pop() non è thread-safe? Ho visto un altro articolo che sostiene il contrario. http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm –

+0

@ Zhongjun'Mark'Jin ha detto che è thread safe .. ma questo non significa non devi considerare gli altri thread. Se un thread apre l'ultimo elemento e poi un altro thread tenta di farlo scoppiare, otterrà IndexError, come dice lui. – fantabolous

Problemi correlati