从单个应用程序中的多个线程调用dll函数是否安全?

时间:2009-04-11 07:26:17

标签: multithreading delphi dll

我正在Delphi 2009中编写一个服务器应用程序,它实现了几种类型的身份验证。每种身份验证方法都存储在一个单独的dll中。第一次使用身份验证方法时,将加载相应的dll。只有在应用程序关闭时才会释放dll。

在服务器线程(连接)之间没有任何形式的同步的情况下访问dll是否安全?

4 个答案:

答案 0 :(得分:17)

简答:

是的,通常可以从多个线程调用DLL函数,因为每个线程都有自己的堆栈,调用DLL函数或多或少与调用自己代码的任何其他函数相同。

答案很长:

如果实际可能取决于使用共享可变状态的DLL函数。

例如,如果您执行以下操作:

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

然后,从不同的线程中使用它肯定是安全。在此示例中,您无法保证在DLL_SetUserDLL_IsAuthenticated之间没有其他线程对DLL_SetUser进行不同的调用。

但是如果DLL函数不依赖于某种预定义状态,即所有必需参数都可以立即使用,并且所有其他配置对于所有线程都是相同的,那么您可以认为它将起作用。

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

但是要小心:DLL函数看起来可能是原子的,但内部使用了某些东西,而不是。例如,如果DLL创建一个总是具有相同名称的临时文件,或者它访问一次只能处理一个请求的数据库,则它将被视为共享状态。 (对不起,我想不出更好的例子)

<强>要点:

如果DLL供应商说,他们的DLL是线程安全的,我会在没有锁定的情况下从多个线程使用它们。如果他们不是 - 或者即使供应商不知道 - 你应该安全地使用锁定。

至少在遇到性能问题之前。在这种情况下,您可以尝试创建多个应用程序/进程来封装您的DLL调用并将它们用作代理。

答案 1 :(得分:4)

为了使您的DLL成为线程安全的,您需要保护一个进程中多个线程可以同时访问的所有共享数据结构 - 在编写DLL代码与编写可执行代码之间没有区别。

对于多个进程,并发访问没有风险,因为每个进程都有自己的DLL数据段,因此从不同的进程看,具有相同名称的变量实际上是不同的。实际上,在不同进程的DLL中提供数据实际上要困难得多,您基本上需要实现与进程间数据交换相同的操作。

请注意,DLL的特殊之处在于,当进程或线程附加到DLL或从DLL分离时,您会收到通知。有关解释,请参阅DllMain Callback Function的文档;有关如何在Delphi编写的DLL中使用此示例的示例,请参阅this article。因此,如果您的线程彼此之间没有完全独立(并且没有共享数据被写访问),那么您将需要一些具有同步访问权限的共享数据结构。各种通知可以帮助您正确设置DLL中的任何数据结构。

如果您的DLL允许完全独立地执行导出的函数,也请检查 threadvar 特定于线程的变量。请注意,对于他们来说初始化 finalization 部分是不可用的,但也许线程通知也可以帮助你。

答案 2 :(得分:0)

这就是事情 - 如果您无法控制源代码(或说明它的文档),您不能认为DLL是线程安全的,因此它假设它们最差。

答案 3 :(得分:-1)

如果你谈论Win32 DLL,如果被多个线程,应用程序调用,它们就是安全的。我不知道你的DLL做了什么,但是如果你的DLL使用像文件或端口这样的可锁定资源,那么根据DLL中的实现可能会有麻烦。

我不熟悉Delphi 2009身份验证DLL的工作。也许您应该将这些信息添加到标题中(您正在专门讨论Delphi 2009 DLL)