Является ли цикл обработки событий Qt безопасным или атомарным? Как это синхронизируется при работе с `QueuedConnection`?

Предположим 2 QThreads работают со следующим соотношением:

connect(&Object1OfThread1, &Object1::Signal, 
        &Object2OfThread2, &Object2::Slot, Qt::QueuedConnection);

Таким образом, когда объект из одного потока генерирует сигнал, вызывается слот другого потока. Как обсуждалось в сигналах Qt (QueuedConnection и DirectConnection), из-за Qt::QueuedConnection, Signal() размещен / добавлен в цикл обработки событий Thread2. Когда приходит очередь, Slot() вызывается.

Вопрос: Является ли сам цикл обработки событий потокобезопасным?
а именно Что делать, если Thread1 и Thread3 одновременно отправляют сигнал в цикл событий Thread2.

2 ответа

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

Как работают сигналы и слоты Qt - Часть 3. Соединения в очереди и между потоками

QueuedConnection опубликует событие в цикле событий для последующей обработки.

При публикации события (в QCoreApplication::postEvent) событие будет помещено в очередь для каждого потока (QThreadData::postEventList). Очередь событий защищена мьютексом, поэтому нет условий гонки, когда потоки отправляют события в очередь событий другого потока.

Как только событие было добавлено в очередь, и если получатель живет в другом потоке, мы уведомляем диспетчера событий этого потока, вызывая QAbstractEventDispatcher::wakeUp, Это разбудит диспетчера, если он спал, ожидая новых событий. Если получатель находится в том же потоке, событие будет обработано позже, поскольку цикл событий повторяется.

Цикл событий Qt является потокобезопасным, но не атомарным.

Поток безопасности

Пока Object2OfThread2 состояние всегда изменяется потоком, связанным с Thread2, не будет никаких гоночных условий. Максимум один слот будет выполнен в любое время.

валентность

Порядок исполнения слотов регулируется:

  • обычное вытеснение потока
  • Порядок, в котором были сделаны подключения к этому слоту.
  • Другие слоты подключены к сигналу.

Поэтому я бы не советовал принимать конкретный порядок выполнения для данного слота.

Что делать, если Thread1 и Thread3 одновременно отправляют сигнал в цикл событий Thread2

  • Во-первых, это разные сигналы: два потока не могут излучать один и тот же сигнал одного и того же объекта, так как этот объект находится только в одном объекте QObject.
  • Сигнал, подключенный первым, побеждает, при условии, что эти сигналы подключены только к Object2OfThread2 даже если они "размещены" одновременно.
  • Например, если сигналы Thread1 подключены к другим сигналам \ слотам, и эти подключения выполняются раньше Object2OfThread2, &Object2::Slotони будут обработаны перед публикацией на Object2OfThread2 цикл событий. Если сигналы испускаются одновременно, сигнал Thread3 будет первым в очереди, поэтому первым будет выполняться.
Другие вопросы по тегам