Einige Diskussion in einer anderen Frage hat mich ermutigt, Fälle besser zu verstehen, in denen Sperren in Multithread-Python-Programmen erforderlich ist.Gibt es Fälle, in denen Python-Threads den gemeinsamen Status sicher manipulieren können?
Pro this Artikel über Threading in Python, habe ich mehrere solide, testbare Beispiele für Fallstricke, die auftreten können, wenn mehrere Threads auf den gemeinsamen Zustand zugreifen. Die beispielhafte Race-Bedingung, die auf dieser Seite bereitgestellt wird, umfasst Rennen zwischen Threads, die eine in einem Wörterbuch gespeicherte gemeinsame Variable lesen und bearbeiten. Ich denke, dass der Fall für ein Rennen hier sehr offensichtlich ist und zum Glück hervorragend überprüfbar ist.
Ich konnte jedoch mit atomaren Operationen wie Listenanfügungen oder variablen Inkrementen keine Wettlaufsituation hervorrufen. Dieser Test versucht, erschöpfend ein solches Rennen zu demonstrieren:
from threading import Thread, Lock
import operator
def contains_all_ints(l, n):
l.sort()
for i in xrange(0, n):
if l[i] != i:
return False
return True
def test(ntests):
results = []
threads = []
def lockless_append(i):
results.append(i)
for i in xrange(0, ntests):
threads.append(Thread(target=lockless_append, args=(i,)))
threads[i].start()
for i in xrange(0, ntests):
threads[i].join()
if len(results) != ntests or not contains_all_ints(results, ntests):
return False
else:
return True
for i in range(0,100):
if test(100000):
print "OK", i
else:
print "appending to a list without locks *is* unsafe"
exit()
ich den Test oben ohne Fehler (100x 100k multithreaded Appends) ausgeführt haben. Kann jemand es zum Scheitern bringen? Gibt es eine andere Klasse von Objekten, die durch atomare, inkrementelle Modifikation durch Threads zum Fehlverhalten gebracht werden können?
Wenden sich diese implizit 'atomaren' Semantiken auf andere Operationen in Python an? Ist das direkt mit der GIL verbunden?
Testen ist keine gültige Methode zum Nachweis der Korrektheit in gleichzeitigen Anwendungen. Es ist sehr einfach für einen bestimmten Test, die Ausführung in einer unerwartet vorhersehbaren Art und Weise zu verschachteln, die niemals das Problem auslösen würde, jedoch die kleinsten Änderungen am Code (d. H.wenn es in eine reale Situation erweitert wird) könnte sofort den Fehler aufzeigen. Die Korrektheit der gleichzeitigen Software sollte bewiesen, nicht getestet werden. – Kylotan