Безопасно ли вызывать функцию dll из нескольких потоков в одном приложении?

Я пишу серверное приложение в Delphi 2009, которое реализует несколько типов аутентификации. Каждый метод аутентификации хранится в отдельной DLL. При первом использовании метода аутентификации загружается соответствующая DLL. DLL освобождается только после закрытия приложения.

Безопасно ли обращаться к DLL без какой-либо синхронизации между потоками сервера (соединениями)?

Ответ 1

Короткий ответ:

Да, как правило, можно вызвать функцию DLL из нескольких потоков, поскольку каждый поток имеет свой собственный стек, а вызов DLL-функции более или менее такой же, как вызов любой другой функции вашего собственного кода.

Длинный ответ:

Если это действительно возможно, зависит от функций DLL с использованием общего измененного состояния или нет.

Например, если вы делаете что-то вроде этого:

DLL_SetUser(UserName, Password)
if DLL_IsAuthenticated then
begin
...
end;

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

Но если функции DLL не зависят от какого-либо предопределенного состояния, то есть все необходимые параметры доступны сразу, а всякая другая конфигурация одинакова для всех потоков, вы можете предположить, что она будет работать.

if DLL_IsAuthenticated(UserName, Password) then
begin
...
end;

Но будьте осторожны: возможно, что DLL-функция выглядит атомарной, но внутренне использует что-то, а это не так. Если, например, если DLL создает временный файл с тем же именем или обращается к базе данных, которая может обрабатывать только один запрос за раз, он считается общим. (Извините, я не мог придумать лучшие примеры)

Резюме:

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

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

Ответ 2

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

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

Обратите внимание, что DLL является особенностью в том, что вы получаете уведомления, когда процесс или поток присоединяется к DLL или отделяется от него. Для пояснения см. Документацию для DllMain Callback Function и this статью для примера, как использовать это в DLL, написанной на Delphi. Поэтому, если ваши потоки не полностью независимы друг от друга (и общие данные не доступны для записи), вам понадобятся некоторые общие структуры данных с синхронизированным доступом. Различные уведомления могут помочь вам правильно настроить любые структуры данных в вашей DLL.

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

Ответ 3

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

Ответ 4

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

Я не знаком с работой DLL файлов проверки Delphi 2009. Возможно, вы должны добавить эту информацию в заголовок (что вы говорите конкретно о DLL Delphi 2009)