Ожидаемый итог — значение счетчика около 200000, так как два потока по 100000 инкрементов каждый.
Анализируйте следующий код на Python, использующий потоковую обработку для увеличения переменной счетчика:
Ожидаемый итог — значение счетчика около 200000, так как два потока по 100000 инкрементов каждый.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Анализируйте следующий код на Python, использующий потоковую обработку для увеличения переменной счетчика:
import threading
import time
counter = 0
def increment():
global counter
for _ in range(100000):
current = counter
counter = current + 1
thread1 = threading.Thread(target=increment)
thread2 = threading.Thread(target=increment)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(f"Итоговое значение счетчика: {counter}")
Объясните, каков ожидаемый вывод, и обсудите возможные проблемы этого кода при использовании потоков.
Ответ
Ожидаемый итог — значение счетчика около 200000, так как два потока по 100000 инкрементов каждый.
Однако из-за отсутствия синхронизации между потоками происходит гонка данных (race condition). Операция counter = current + 1 не атомарна: поток читает значение, увеличивает и записывает обратно. Если оба потока прочитают одно и то же значение одновременно, один из инкрементов потеряется.
В итоге итоговое значение счетчика будет меньше 200000 и варьироваться при разных запусках.
Чтобы исправить, нужно использовать блокировку (например, threading.Lock) для защиты критической секции:
import threading
counter = 0
lock = threading.Lock()
def increment():
global counter
for _ in range(100000):
with lock:
counter += 1
Это гарантирует, что только один поток изменяет counter в момент времени, и итог будет корректным.