Bezpieczeństwo wątków w słowniku Pythona

105

Mam klasę, która zawiera słownik

class OrderBook:
    orders = {'Restaurant1': None,
              'Restaurant2': None,
              'Restaurant3': None,
              'Restaurant4': None}

    @staticmethod
    def addOrder(restaurant_name, orders):
        OrderBook.orders[restaurant_name] = orders

Uruchamiam 4 wątki (po jednym dla każdej restauracji), które wywołują metodę OrderBook.addOrder. Oto funkcja uruchamiana przez każdy wątek:

def addOrders(restaurant_name):

    #creates orders
    ...

    OrderBook.addOrder(restaurant_name, orders)

Czy to jest bezpieczne, czy muszę użyć zamka przed zadzwonieniem addOrder?

nmat
źródło
2
jak może wystąpić problem, gdy każdy wątek i tak zapisuje do innego klucza.
Jochen Ritzel,
64
@Jochen: w zależności od tego, jak zostaną zaimplementowane dyrektywy, wiele może się nie udać. To bardzo rozsądne pytanie.
Ned Batchelder,

Odpowiedzi:

95

Wbudowane struktury Pythona są bezpieczne dla wątków dla pojedynczych operacji, ale czasami może być trudno zobaczyć, gdzie instrukcja naprawdę staje się operacją wielokrotną.

Twój kod powinien być bezpieczny. Pamiętaj: zamek w tym miejscu prawie nie zwiększy kosztów i zapewni ci spokój.

http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm zawiera więcej szczegółów.

Ned Batchelder
źródło
6
Oto effbot.org Why-to / how-to o wdrażaniu zamka
hobs
1
Należy rozważyć pojedynczą operację w porównaniu z operacjami złożonymi, takimi jak get-add-set .
andy
5
Problem w tym, że kiedy często czytam / piszę ten dykt, ten spokój będzie mnie dużo kosztował.
Shihab Shahriar Khan
2
„zamek tutaj prawie nie zwiększy kosztów”: dlaczego tak jest?
maksymalnie
32

Tak, wbudowane typy są z natury bezpieczne dla wątków: http://docs.python.org/glossary.html#term-global-interpreter-lock

Upraszcza to implementację CPython, czyniąc model obiektowy (w tym krytyczne typy wbudowane, takie jak dict ) niejawnie zabezpieczony przed równoczesnym dostępem.


źródło
25
To nie jest funkcja Pythona, ale cpythona .
phihag
8
To prawda, ale jak rozumiem, wbudowane w Jythonie i IronPythonie są również bezpieczne dla wątków nawet bez użycia GIL (a pusta jaskółka, jeśli kiedykolwiek się pojawi, proponuje również pozbyć się GIL). Założyłem, że skoro nie podał interpretera, którego używa, to miał na myśli w CPythonie.
1
Prawidłowo w przypadku Jythona
Evgeni Sergeev
9

Przewodnik stylistyczny Google odradza poleganie na atomowości dyktowania

Bardziej szczegółowo wyjaśniono w: Czy przypisanie zmiennych w Pythonie jest atomowe?

Nie polegaj na atomowości typów wbudowanych.

Chociaż wbudowane typy danych Pythona, takie jak słowniki, wydają się mieć operacje atomowe, istnieją przypadki narożne, w których nie są one atomowe (np. Jeśli __hash__lub __eq__są zaimplementowane jako metody Pythona) i nie należy polegać na ich atomowości. Nie powinieneś też polegać na przypisywaniu zmiennych atomowych (ponieważ to z kolei zależy od słowników).

Użyj Queuetypu danych Queue modułu jako preferowanego sposobu przesyłania danych między wątkami. W przeciwnym razie użyj modułu obsługi wątków i jego elementów podstawowych. Dowiedz się, jak prawidłowo używać zmiennych warunkowych, aby móc ich używać threading.Conditionzamiast blokad niższego poziomu.

I zgadzam się z tym: w CPythonie jest już GIL, więc wydajność korzystania z Locka będzie znikoma. O wiele bardziej kosztowne będą godziny spędzone na poszukiwaniu błędów w złożonej bazie kodów, gdy te szczegóły implementacji CPythona zmienią się pewnego dnia.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło