Остановить поток: флаг против события [дубликат]


На этот вопрос уже есть ответ здесь:

Я видел примеры например, здесь использования Event Чтобы остановить поток, где я думаю, что логический флаг будет делать эту работу.

Событие

class MyThread(threading.Thread):

    def __init__(self):
        self._please_stop = threading.Event()

    def run(self):
        while not self._please_stop.is_set():
        [...]

    def stop(self):
        self._please_stop.set()

Флаг

class MyThread(threading.Thread):

    def __init__(self):
        self._please_stop = False

    def run(self):
        while not self._please_stop:
        [...]

    def stop(self):
        self._please_stop = True

Какая польза от использования Event здесь? Его Метод wait не используется. Что делает его лучше, чем логический флаг?

Я вижу смысл, если один и тот же Event разделяется между несколькими потоками, но в остальном я его не понимаю.

Этот поток рассылки предполагает, что Event будет безопаснее, но мне непонятно, почему.

Точнее, я не понимаю эти два абзаца:

Если я правильно понимаю GIL, он синхронизирует весь доступ к Структуры данных Python (такие как my boolean флаг "прекращено"). Если что в таком случае, зачем утруждать себя использованием резьбы.Мероприятие для этой цели?

GIL является деталью реализации и полагается на нее для синхронизации вещи для вас не защищают от будущего. У вас, вероятно, будет много предупреждение, но с использованием резьбы.Event () не сложнее, и это больше правильно и безопаснее в долгосрочной перспективе.

Я согласен, что использование Event добавляет почти никаких накладных расходов, поэтому я могу придерживаться этого, но я хотел бы понять пределы флаг приближается.

(я использую Python3, поэтому меня не волнуют ограничения Python2, если таковые имеются, хотя они полностью заслуживают упоминания здесь.)

2 6

2 ответа:

Я думаю, что подразумевается в потоке, который вы цитируете, что установка булева не обязательно является атомной операцией в Python. В то время как наличие глобальной блокировки на всех объектах Python (GIL) делает все операции, устанавливающие атрибут , атомарными на данный момент, такая блокировка может не существовать в будущем. Использование Event делает операцию атомарной, поскольку она использует собственную блокировку для доступа.

Ссылка для atomic - это вопрос Java, но он не менее важен, потому что об этом.

Программирование часто заключается не только в том, чтобы заставить код работать сегодня, но и в том, чтобы заставить его работать через изменения, которые будут сделаны в будущем.

  • другие реализации Python не имеют GIL. Захочу ли я запустить его на pypy завтра?
  • На самом деле, мне нужно распределить работу по нескольким процессам. Поменяйтесь местами multiprocessing... который реализует Event(), но потерпит неудачу, если вы просто используете локальную переменную.
  • Получается, что код должен остановиться только в том случае, если несколько других нитей считают, что так и должно быть. Ну, используйте Semaphore() вместо Event()... но было бы легко реализовать неправильно с переменными.
Таким образом, вполне вероятно, что вы можете писать многопоточные программы совершенно правильно на Python, полагаясь на то, как байт-код прерывается и когда GIL может быть выпущен... но если я буду читать и изменять ваш код позже, я был бы гораздо счастливее, если бы вы использовали стандартные примитивы синхронизации.