Как работают обратные вызовы и глобальная синхронизация данных

#c #unix #callback #synchronization #global-variables

#c #unix #обратный вызов #синхронизация #глобальные переменные

Вопрос:

У меня возникают некоторые трудности с пониманием обратных вызовов и потока программ, проблем с синхронизацией.

Допустим, у меня есть глобальная переменная g_peers. И я регистрирую обратный вызов в системном приложении, которое уведомит меня об одноранговых событиях, таких как — joins / leave / change . Теперь в обратном вызове я изменяю g_peers на основе события и связанной с ним информации. В других частях кода (т.Е. В обычном потоке кода) У меня есть функции, которые считываются из g_peers.

Теперь это приведет к проблемам с синхронизацией? Допустим, я нахожусь в процессе чтения из g_peers, когда одноранговый узел уходит и вызывается обратный вызов, который изменяет g_peers.

Как работает обратный вызов? Прерывается ли обычный поток до завершения обратного вызова?

Ответ №1:

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

Что такое обратный вызов?

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

Комментарии:

1. Моя программа однопоточная. Делает ли обратный вызов многопоточным?

2. @HappyGoLucky: Нет, это не так. Хорошим примером однопоточного фреймворка является Brew Framework, который использует обратные вызовы.

3. Давайте возьмем пример, который я привел в своем вопросе. Допустим, в основном цикле программы есть функция DisplayPeers(), которая в данный момент выполняется. В цикле for информация о каждом узле выводится на экран. Во время этого вызывается обратный вызов, и обратный вызов присваивает g_peers значение 0. После завершения обратного вызова управление возвращается к DisplayPeers. Он продолжается там, где он остановился. Но теперь g_peers пуст. Не вызовет ли это проблемы?

4. @HappyGoLucky: поведение конкретно зависит от используемой вами платформы и от того, как она поддерживает обратный вызов в однопоточной среде. Обратный вызов может вообще не быть асинхронным в некоторых фреймворках. Вам нужно будет проверить документацию любого используемого вами fwk.

5. Я не использую какие-либо фреймворки как таковые. Просто простая программа на c в unix.