Nie jest szczęśliwy ;-) Odpowiedź na to pytanie. Nie ma w tym nic gwarantowanego, co możesz potwierdzić, zauważając, że instrukcja obsługi Pythona nie daje żadnych gwarancji co do atomowości.
W CPython jest to kwestia pragmatyki. Jak mówi krótka część artykułu w effbot,
W teorii oznacza to, że dokładna księgowość wymaga dokładnego zrozumienia implementacji kodu bajtowego PVM [Python Virtual Machine].
I taka jest prawda. CPython ekspert wie L += [x]
jest atomowy, bo wiedzą, wszystkie z poniższych:
+=
kompiluje się do kodu bajtowego INPLACE_ADD
.
- Implementacja
INPLACE_ADD
dla obiektów listy jest napisana w całości w C (kod Pythona nie znajduje się na ścieżce wykonania, więc GIL nie może zostać zwolniony między bajtów).
- W
listobject.c
implementacja INPLACE_ADD
jest funkcją list_inplace_concat()
i nic podczas jej wykonywania nie musi wykonywać żadnego kodu Pythona użytkownika (jeśli tak, GIL może ponownie zostać zwolniony).
To wszystko może wydawać się niesamowicie trudne do zachowania prosto, ale dla kogoś, kto ma wiedzę na temat wewnętrznych elementów CPythona (w momencie pisania tego artykułu), tak naprawdę nie jest. W rzeczywistości, biorąc pod uwagę, że głębokość wiedzy, to wszystko jest raczej oczywiste ;-)
Więc w gruncie pragmatyki eksperci CPython zawsze swobodnie powoływać się na, że „operacje, które«wyglądają atomowy»powinno być naprawdę atomowy” , a także kierowało niektórymi decyzjami językowymi. Na przykład, operacja brakuje listy effbot użytkownika (dodane do języka po napisaniu tego artykułu):
x = D.pop(y) # or ...
x = D.pop(y, default)
jeden argument (w tym czasie) za dodanie dict.pop()
właśnie, że oczywiste implementacja C byłoby atomowy , podczas gdy w trakcie używania (w tym czasie) Alternatywnie:
x = D[y]
del D[y]
nie atomowe (wyszukiwania i usunięcie dokonuje się za pomocą różnych bytecodes tak gwinty można przełączać między nimi).
Ale doktorzy nigdy nie mówili , że.pop()
był atomowy i nigdy nie będzie. Jest to rzecz "przyzwolenie dorosłych": jeśli jesteś ekspertem na tyle, aby świadomie wykorzystać to, nie potrzebujesz trzymania ręki. Jeśli nie masz wystarczającej wiedzy eksperckiej, obowiązuje ostatnie zdanie artykułu o effbot:
W razie wątpliwości użyj muteksu!
W gruncie pragmatycznego konieczności rdzeniowe deweloperzy nigdy nie złamie niepodzielność przykładów effbot (lub z D.pop()
lub D.setdefault()
) w CPython. Inne implementacje nie są wcale zobowiązane do naśladowania tych pragmatycznych wyborów. Rzeczywiście, ponieważ atomowość w tych przypadkach opiera się na specyficznej formie kodu bajtowego CPythona w połączeniu z korzystaniem przez CPythona z globalnej blokady interpretera, która może być zwolniona tylko między bajtodami, może to być prawdziwy ból dla innych implementacji, aby naśladować te kody.
I nigdy nie wiadomo: niektóre przyszłe wersje CPython mogą również usunąć GIL! Wątpię w to, ale teoretycznie jest to możliwe. Ale jeśli tak się stanie, założę się, że utrzymana zostanie również wersja równoległa zachowująca GIL, ponieważ cała masa kodu (zwłaszcza modułów rozszerzeń napisanych w C
) opiera się również na GIL dla bezpieczeństwa wątków.
warto powtarzać:
W przypadku wątpliwości, należy mutex!
To dla mnie naprawdę zaskakujące - nie spodziewałbym się, że tak się stanie. Mam nadzieję, że ktoś wyraźnie to wyjaśni. –
Chociaż przegłosowałem to, myślę, że stwierdzenie "Które operacje w Pythonie są gwarantowane jako bezpieczne, a które nie?" potępia pytanie o szerokie zamknięcie. Czy mógłbyś to przeformułować? – Bathsheba
Czekając na pewne ograniczenia dodane do pytania, znalazłem effBot ponownie: [Jaka mutacja globalnej wartości jest bezpieczna dla wątków?] (Http://effbot.org/pyfaq/what-kinds-of-global-value-mutation -are-thread-safe.htm) ciekawa lektura.Proponuję przeformułowanie na: "Jakie rodzaje globalnej mutacji wartości są bezpieczne dla wątków", aby być miłym zagrożeniem ;-) W odniesieniu do próbki listy: Lista jest bezpieczna dla wątków w swoich operacjach, ale same dane nie są "zabezpieczone" przez pojemnik. Tak więc każdy dostęp do zawartości zmieniającej element listy będzie cierpieć jako liczba całkowita "+ = 1". – Dilettant