Потоки POSIX: лучший метод прерывания

Первое, что мне сказали, когда я начал работать с pthreads, было - вы должны избегать принудительной отмены потока, например, pthread_cancel. Вместо этого мы должны использовать уведомление об отмене потока через канал связи потоков.

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

loop {
    process_chunk();
    if (check_cancel_flag())
        break;
}

Но как лучше реализовать эту функцию check_cancel_flag()?

При всем моем опыте в c и linux я могу вспомнить только эти методы:

  1. (Если у вас есть только один рабочий поток) Вы можете использовать sig_atomic_t в качестве типа для флага отмены. Проверьте его в функции check_cancel_flag() и отметьте его как true в обработчике сигнала потока. Затем просто вызовите pthread_kill из основного потока.

  2. Используйте любой тип POD для флага отмены и защитите его мьютексом. В этом случае вы слишком часто будете получать накладные расходы на блокировку вызова.

  3. Использовать мьютекс в качестве флага отмены. Проверьте это вызовом pthread_mutex_trylock. Если основной поток освобождает этот мьютекс, пора завершить работу рабочего потока.

  4. (Для C11) Используйте встроенные функции gcc _atomic (или другую библиотеку asm atomic) для установки и проверки флага отмены.

Я больше ничего не мог вспомнить.

Вопрос: Как выбрать правильный подход? Знаете ли вы какие-либо ориентиры по этой проблеме?


person John Green    schedule 28.06.2017    source источник
comment
Существует Вики-статья, в которой обсуждается точный вопрос.   -  person Eugene Sh.    schedule 28.06.2017
comment
Я думаю, что это немного по-другому, только для реализации потребителя/производителя. Действительно, я использую очередь и условия ожидания, но как прервать длинную задачу?   -  person John Green    schedule 28.06.2017
comment
Кстати, C11 имеет простую квалификацию _Atomic для типов данных, которая помогает. sig_atomic_t никогда не подходит, его единственные гарантии относятся к обработчикам сигналов, и там он гарантирует только неделимость, а не другие свойства согласованности памяти, которые вы хотели бы иметь.   -  person Jens Gustedt    schedule 28.06.2017
comment
Я писал про atomic в C11. Я предполагал использовать sig_atomic_t, когда у нас есть один рабочий поток, и редактировать его только в обработчике сигналов текущего потока.   -  person John Green    schedule 28.06.2017


Ответы (1)


Альтернативой является использование блокировки чтения-записи (pthread_rwlock_t) для защиты флага, так как ваши рабочие потоки должны часто читать его, но он записывается только один раз.

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

person caf    schedule 29.06.2017