Я наткнулся на этот вопрос и был очень впечатлен этот ответ.
Мне бы очень хотелось последовать советам из этого ответа, но я не представляю, как это сделать. Как избежать многопоточности?
Часто возникают ситуации, когда необходимо иметь дело с разными вещами одновременно (например, с разными аппаратными ресурсами или сетями), но в то же время им нужен доступ к общим данным (например, конфигурациям, данным для работы и т. Д.). Как это можно решить в однопоточном режиме без использования каких-либо огромных конечных автоматов или циклов событий?
Я знаю, что это огромная тема, на которую невозможно ответить в целом на такой платформе, как Stackoverflow. Я думаю, мне действительно стоит прочитать рекомендованную книгу из упомянутого ответа, но сейчас я хотел бы прочитать здесь некоторые комментарии.
Возможно, стоит отметить, что меня интересуют решения на C. Более высокие языки, такие как Java, C ++ и особенно фреймворки, такие как Qt или подобные, значительно упрощают это, но как насчет чистого C?
Любой вклад очень ценится. Спасибо всем заранее
3 ответа
Вы уже упоминали циклы событий, но я все же считаю, что они являются отличной альтернативой многопоточности для многих приложений, а также служат хорошей базой при добавлении многопоточности позже, если это оправдано.
Предположим, у вас есть приложение, которое должно обрабатывать ввод данных пользователем, данные, полученные через сокет, события таймера и сигналы, например:
Один многопоточный дизайн будет заключаться в том, чтобы порождать разные потоки для ожидания различных источников событий и синхронизации их действий с некоторым глобальным состоянием по мере поступления событий. Это часто приводит к беспорядочной логике синхронизации и завершения.
Однопоточная конструкция должна иметь унифицированный цикл обработки событий, который принимает все типы событий и обрабатывает их в том же потоке, в котором они поступают. В системах * nix это можно сделать, например,
select(2)
,poll(2)
илиepoll(7)
(последнее относится к Linux). В последних версиях Linux также естьsignalfd(2)
,timerfd
(timerfd_create(2)
) иeventfd(2)
для точной подгонки дополнительных типов событий в эту модель, а в других модулях вы можете использовать различные приемы, включающие напримерpipe(2)
для сигнализации событий. Хорошая библиотека, которая абстрагирует большую часть этого, - это libevent, который также работает на других платформах.
Помимо того, что не нужно сразу иметь дело с многопоточностью, подход с использованием цикла событий также позволяет добавлять многопоточность позже, если это необходимо для производительности или по другой причине: вы просто позволяете обработчику событий создавать потоки для определенных событий. Хранение всей обработки событий в одном месте часто значительно упрощает дизайн приложения.
Когда вам действительно нужно несколько потоков (или процессов), полезно иметь узкие и хорошо протестированные интерфейсы между ними, например, используя синхронизированные очереди. Альтернативный дизайн для обработчика событий мог бы заключаться в том, чтобы потоки, генерирующие события, отправляли события в очередь событий, из которой обработчик событий затем считывает и отправляет их. Это четко разделяет различные части программы.
Вы можете реализовать параллельные задачи, используя сопрограммы. Затем вам нужно явно передать управление (процессор) другой сопрограмме. Это не будет выполнено автоматически прерыванием после небольшой задержки.
http://en.wikipedia.org/wiki/Coroutine
Подробнее о продолжениях и стиль передачи продолжения (и преобразование CPS).
CPS-преобразование может быть систематическим способом имитации многопоточности.
Вы можете ознакомиться с CPC ( Continuation Passing C , Юлиуш Хробочек и Габриэль Кернейс), который также является источником для трансформатора C. Вы также можете прочитать старую книгу Аппеля: Компиляция с продолжениями и книга Queinnec Lisp In Small Pieces < / em>
Также читайте подробнее о циклах событий, обратные вызовы, закрытия, стеки вызовов, хвостовые вызовы. Эти понятия связаны с вашими проблемами.
См. Также (почти устаревший) setcontext (3) Linux функции и функций ожидания в циклах событий см. в этом.
Похожие вопросы
Связанные вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.