MiddleДебаггингЧастоЕщё не отвечали
Почему этот многопоточный счётчик неверен и как его исправить?
Пять потоков увеличивают counter по 100000 раз, но итоговое значение слишком мало.
import threading
counter = 0
def inc():
global counter
for _ in range(100000):
counter += 1
threads = [threading.Thread(target=inc) for _ in range(5)]
for t in threads: t.start()
for t in threads: t.join()
print(counter) # обычно < 500000
Найдите и исправьте ошибку.
Гонка данных: counter += 1 — это «чтение-изменение-запись», не атомарная на уровне байткода, поэтому потоки чередуются и теряют обновления; GIL гарантирует атомарность байткода, но не многошаговых операций. Решение: защитить инкремент через threading.Lock.
- ✗Считать, что GIL делает
+=атомарным между потоками - ✗Винить тайминг print, а не потерянные обновления
- ✗Думать, что один
globalделает инкремент потокобезопасным
- →Почему GIL гарантирует атомарность байткода, но не атомарность оператора?
- →Когда
itertools.countилиqueue.Queueчище решения с блокировкой?