2010-02-09 7 views

Antwort

39

Sie müssen Ihre eigenen Sperren für alle gemeinsam genutzten Variablen implementieren, die in Python geändert werden. Sie müssen sich keine Sorgen über das Lesen von den Variablen machen, die nicht geändert werden (dh gleichzeitige Lesevorgänge sind in Ordnung), so unveränderliche Typen (frozenset, tuple, str) sind wahrscheinlich sicher, aber es würde nicht weh tun. Für Dinge, die Sie ändern werden - list, set, dict, und die meisten anderen Objekte, sollten Sie Ihren eigenen Sperrmechanismus haben (während In-Place-Operationen auf den meisten von ihnen ok sind, können Threads zu super-bösen Bugs führen - Sie könnten auch Sperren implementieren, es ist ziemlich einfach).

By the way, ich weiß nicht, ob Sie das wisst, aber Verriegelung ist in Python sehr einfach - erstellen threading.lock Objekt, und dann können Sie erwerben/loslassen wie folgen aus:

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: from __future__ import with_statement; Python 2.4 und bevor das nicht haben, so dass Sie die acquire()/Release() ruft in try:...finally: Blöcke setzen wollen werden:

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

Ich glaube, dass jemand, der Threading Locks noch nicht benutzt hat, darauf achten sollte, dass die Sperre (in Ihrem Beispiel 'list1Lock') * zwischen den Threads * geteilt werden sollte, damit es korrekt funktioniert. Zwei unabhängige Sperren, eine für jeden Thread, würden nichts verriegeln, nur dummes Overhead hinzufügen. – tzot

+0

Sollte das nicht sein: mit list1Lock: # Do sachen –

+0

@ slack3r Guter Anruf! –

3

Sie sind Thread-sicher, solange Sie den GIL in C-Code für den Thread nicht deaktivieren.

+5

Dies ist ein Implementierungsdetail von CPython, auf das Sie nicht weiterleiten sollten. Es wird möglicherweise in Zukunft zum Zufall und andere Implementierungen haben es nicht. –

+0

Georg - dieser Aspekt von Python Art von terrefies mich. Vergessen Sie nicht alle Bugs, die aus Java-Programmen herausfallen, wenn 8 Kerne auf dem Desktop üblich werden - was passiert, wenn GIL entfernt wird und Multithread-fähige Python-Apps plötzlich auf 8 Kernboxen laufen? – Ben

+3

Es sollte niemanden erschrecken, wenn sie nicht vorgeben, dass ihr Code Thread-sicher ist, wenn es nicht eindeutig ist. :) – Kylotan

7

Ja, aber Sie müssen noch vorsichtig natürlich

Zum Beispiel sein:

Wenn zwei Threads zu pop() aus einer Liste sind Rennen mit nur einem Einzelteil, Ein Thread das Einzelteil erhält erfolgreich und die andere werden eine IndexError

-Code erhalten, wie diese

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

Sie sollten nicht Thread-sicher ist wr ite it this

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

Ich möchte pop() threadsafe, aber ich kann diese Tatsache nirgendwo in der Dokumentation finden. Kann jemand mir helfen, diese Behauptung zu erhalten, bevor ich es als Evangelium nehme? –

+0

Wirklich? list.pop() ist nicht Thread-sicher? Ich sah einen anderen Artikel, der das Gegenteil behauptete. http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm –

+0

@ Zhongjun'Mark'Jin er sagte, es ist Thread sicher .. aber das heißt nicht Sie müssen die anderen Threads nicht berücksichtigen. Wenn ein Thread das letzte Element aufruft und dann ein anderer Thread versucht, ebenfalls zu knacken, wird er IndexError erhalten, wie er sagt. – fantabolous

Verwandte Themen