Сигнальное и несигнальное состояние события

Это может быть вопрос не программирования для всех, я прочитал о объектах синхронизации потока, таких как event, и о том, как он настроен как сигнализированное или не сигнализированное состояние. Однако я не мог понять эти термины с сигнализацией и без сигнализации. Каждый из них выражался по-разному, и я немного запутался.

  • В этой ссылке указано, что

    Сигнальное состояние указывает, что ресурс доступен для процесса или потока для его использования. Не сигнализированное состояние указывает, что ресурс используется.

  • Я получил презентацию Power Point с сайта университета, в которой говорится, что

    Объект, находящийся в сигнальном состоянии, не приведет к тому, что поток, который ожидает объект для блокирования, и объект, который не находится в сигнальном состоянии, вызовет какой-либо поток, который ожидает, чтобы этот объект блокировался, пока объект снова не станет сигналом.

  • Эта третья ссылка утверждает, что это

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

Простое объяснение этой концепции с примером будет действительно полезно.

Ответ 1

Хорошо, ваши 3 цитаты не являются несовместимыми. Но отпустите немного до реализации:

Каждый возвращаемый объект имеет прикрепленное к нему логическое значение, называемое сигнальным состоянием, которое используется для ожидания этого объекта; если объект сигнализируется, то функции ожидания будут не ждать его; если объект не сигнализирован, функции ожидания будут ждать.

Теперь, как это относится к определенному типу объекта? Это зависит от природы объектов и, в частности, от семантики, связанной с ее ожиданием. Фактически, сигнализированное состояние определяется в терминах состояния ожидания. Например (см. документы для подробностей):

  • Мьютекс сигнализируется, когда он не принадлежит.
  • Процесс/поток передается по завершении.
  • Семафор сигнализируется, когда его количество больше 0.
  • Ожидаемый таймер сигнализируется, когда он истек.

Вам может показаться лучше, если бы мьютекс был зарегистрирован, когда он принадлежал, но на самом деле это не так. Это необходимо для правильной работы функций ожидания.

А как насчет событий? Ну, это несколько простые объекты, вы можете сигнализировать и де-сигнализировать их по желанию, поэтому состояние сигнала не имеет никакого дополнительного значения:

  • : нити не будут ждать его.
  • non-signaled: Threads будет ждать его.

События также имеют такие SignalPulse и AutoReset вещи, которые немного отличаются (и IME практически невозможно использовать правильно).

Теперь посмотрим на ваши цитаты:

Сигнальное состояние указывает, что ресурс доступен для процесса или потока для его использования. Не сигнализированное состояние указывает, что ресурс используется.

Собственно, это интерпретация. Обычно есть ресурс, который вы пытаетесь провести арбитраж, и обычно вы ждете, если и только, если этот ресурс используется, поэтому он делает эквивалентность между ресурсами в использовании и ожиданием ресурса. Но это не техническое требование, просто обычный прецедент.

Объект, находящийся в сигнальном состоянии, не приведет к тому, что поток, который ожидает объект для блокирования, и объект, который не находится в сигнальном состоянии, вызовет какой-либо поток, который ожидает, чтобы этот объект блокировался, пока объект снова не станет сигналом.

Правильно и точно!

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

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

Ответ 2

Легкий способ подумать об этом: "signaled" = "зеленый свет"

Green Light Если вы едете, и вы видите зеленый свет, который вы не останавливаете (это нить, смотрящая на событие, обнаруживая сообщение и продолжая без блокировки).

enter image description here Если вы видите красный свет, который вы остановите, и дождитесь, пока он станет зеленым, а затем продолжите (безопасно в понимании, что другие потоки теперь не сигнализируются, поэтому ждут или будут ждать их... красного света!)

Ответ 3

Ну, на самом деле все эти объяснения конгруэнтны.

Самое упрощенное (и, следовательно, не 100% точное) объяснение события - это увидеть событие как услугу флага, предоставляемую операционной системой. Сигнальное событие можно увидеть как установленный флаг, с другой стороны, событие с несанкционированным доступом можно рассматривать как флаг отмены.

Для реализации потоковой системы производителя/потребителя, основанной на флагах, вы обычно делаете что-то вроде следующего (обратите внимание на простоту, я пренебрегаю дальнейшими механизмами синхронизации):

static volatile int  flag = 0;
static volatile char data = 'A';

// Some code to initialize the threads  

void producer()
{
    while (1)
    {
        Sleep(1000);
        data++;
        flag = 1;
    }
}

void consumer()
{
    while (1)
    {
        /* Busy wait for the occurence of more data */
        while (!flag)
        {
            // wait for next data
        }

        flag = 0;

        // process data
    }
}

К несчастью, это приведет к расходу процессорных циклов в замкнутом цикле ожидания или нежелательной отсрочке выполнения из-за вызова Sleep, введенного для снижения потребления ЦП. Оба нежелательны.

Чтобы избежать таких проблем при синхронизации задач, операционные системы предоставляют различные механизмы, подобные флагам (например, события в Windows). С событиями установка и сброс флага выполняется с помощью вызовов OS SetEvent/ResetEvent. Чтобы проверить флаг, вы можете использовать WaitForSingleObject. Этот вызов имеет право поставить задачу в режим ожидания до тех пор, пока не будет сообщено о событии, которое будет оптимальным с точки зрения потребления ЦП.

Это приводит к тому, что приведенный выше пример выглядит следующим образом:

static volatile char data = 'A';
static HANDLE newDataEvent = INVALID_HANDLE_VALUE;

// Some code to initialize the threads and the newDataEvent handle  

void producer()
{
    while (1)
    {
        Sleep(1000);
        data++;
        SetEvent(newDataEvent);
    }
}

void consumer()
{
    while (1)
    {
        if (WaitForSingleObject(newDataEvent, INFINITE) == WAIT_OBJECT_0)
        {
            ResetEvent(newDataEvent);
            // process data
        }
    }
}

Ответ 4

Я не очень согласен с другими ответами. Они упускают суть:

  • если свойство signaled имеет значение true => событие произошло раньше.

  • если сигнализируемое свойство равно false => событие не произошло до сих пор.

Где "свойство сигнала ложно " равно "свойство не сигнала истинно ".

И все три определения относятся к потокам, но они не ясны, потому что определение сигнала происходит не от многопоточности, а от низкоуровневого программирования.

Сигналы поступают от прерываний:
msgstr "если этот сигнал становится высоким (= прерывание), переместите указатель выполнения на эту функцию".
Это значение сигнала, и оно происходит от прерываний, а не от потоков. Итак, не сигнализированные средства, сигнал не стал высоким до сих пор.

В потоке это звучит так: "Потоку необходимо, чтобы событие продолжалось. Если это произошло раньше, оно может продолжиться; в противном случае он блокирует себя и ожидает его".