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

问题描述 投票:12回答:4

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

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

multithreading delphi dll
4个回答
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是线程安全的,我会在多线程中使用它们而不加锁。如果它们不是--甚至如果厂商不知道--你应该安全地使用锁定。

至少在你遇到性能问题之前是这样。在这种情况下,你可以尝试创建多个applicationsprocesses,这些applicationsprocesses包裹着你的DLL调用,并将它们作为代理。


4
投票

为了使你的DLLs线程安全,你需要保护一个进程中的多个线程可以并发访问的所有共享数据结构--为DLL写代码和为可执行文件写代码在这里没有区别。

对于多个进程来说,并发访问并不存在风险,因为每个进程都会得到自己的DLL数据段,所以从不同的进程看到的同名变量其实是不同的。 其实要在DLL中提供从不同进程看一样的数据要困难得多,你基本上需要实现与进程间数据交换一样的东西。

需要注意的是,DLL的特殊性在于,当一个进程或一个线程附加或脱离DLL时,你会得到通知。请参阅文档中的 DllMain回调函数 解释,以及 本文 的例子来了解如何在Delphi编写的DLL中使用它。因此,如果你的线程之间不是完全独立的(没有共享数据是写访问的),那么你将需要一些同步访问的共享数据结构。各种通知可能会帮助你正确设置你的DLL中的任何数据结构。

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


1
投票

事情是这样的--如果你不能控制源码(或文档说明它是安全的),你就不能假设DLL是线程安全的,所以你应该假设它不是...。


-1
投票

如果你说的是Win32的DLL,如果被多个线程、应用程序调用,它们是要安全的。我不知道你的DLL是做什么的,但如果你的DLL使用的是文件或端口等可锁定的资源,那么根据DLL里面的实现,可能会有麻烦。

我不熟悉Delphi 2009认证DLL的工作情况。也许您应该在标题中添加这些信息(您是在专门讨论Delphi 2009 DLLs的问题

© www.soinside.com 2019 - 2024. All rights reserved.