#c #многопоточность
Здравствуйте. Был на собеседовании... В итоге озадачили следующим вопросом (примерно). Вот, допустим, есть сишная либа в исходниках... Там куча глобальных переменных... Но она писалась не под многопоточные приложения... Что можно сделать, чтобы обеспечить более-менее адекватное использование этой либы в многопоточных приложениях, притом, что существенно менять исходники нельзя(да и слишком непосильная задача будет)? В общем, что-то нужно сделать с глобальными переменными, но что?
Ответы
Ответ 1
Один [наивный] подход - разнести вызовы этих функций из разных потоков по времени, т.е. заоболочить каждый вызов в критическую секцию. Однако имейте в виду, что такой подход не будет применим, если рассматриваемые глобальные переменные используются для сохранения состояния между вызовами этих функций. Если учесть, что в 9 случаях из 10 глобальные переменные заводятся именно для таких целей, применимость такого подхода выглядит сомнительной. Например (не ходя далеко за примером), сериализация вызовов стандартной функции strtok из разных потоков через критическую секцию никак не сделает ее работоспособной в многопоточной среде, ибо она использует глобальную переменную для сохранения состояния между вызовами. (Интересно было бы поспорить на тему того, можно ли таким образом адаптировать к многопоточности функцию rand(), которая, как известно, тоже обладает сохраняемым между вызовами состоянием :) ) Второй подход - разнести конфликты между этими функциями в пространстве (в памяти). А именно: объявить все глобальные переменные, как thread local, используя С11 спецификатор _Thread_local. Это не потребует какого-то существенного изменения исходников. (Многие пре-С11 компиляторы С давно предоставляют аналогичную функциональность в качестве расширения - тот же __thread в GCC или __declspec(thread) в MSVC.) Этот подход несравнимо более надежен, но опять же, вопрос тут в том, устроит ли вас ситуация, когда в каждом потоке функции библиотеки будут вести себя "изолированным" образом по отношению к глобальным данным, т.е. устроят ли вас, к примеру, изолированные счетчики открытых файлов, изолированные глобальные флаги состояния и т.п. Так что работоспособность такого подхода тоже не является очевидной.Ответ 2
Много зависит от самой библиотеки, если библиотека обрабатывает данные в памяти, то использование мьютексов легко реализуемый вариант. Но если библиотека работает с системой ввода/вывода то лучше реализовать отдельный поток для работы с библиотекой и работать с ним через мьютексы и сигнальные переменые.
Комментариев нет:
Отправить комментарий