DLL 线程安全
Posted
技术标签:
【中文标题】DLL 线程安全【英文标题】:DLL thread safety 【发布时间】:2011-01-02 15:58:30 【问题描述】:我正在使用 MS VC express c++ 开发一个 DLL,它将同时加载到多个客户端应用程序中,该 DLL 具有使用 data_seg(".SHARED_SPACE_NAME")
创建的共享内存空间。在这个共享内存空间中有一些可以修改的向量。
假设我们在 DLL 主体中有一个名为 doCalc() 的函数:
_DLLAPI void __stdcall doCalc(int argument)
//Add to vector
//Loop through vector
//Erase from vector
//etc.
如果同时从两个或多个客户端应用程序调用doCalc
,系统将崩溃。
我希望 doCalc 调用“排队等待”以完成上一个调用 - 就像它是一个单线程应用程序一样。
因此,如果客户端 1 调用,然后在客户端 2 调用之后立即调用,那么客户端 1 应该完成该函数,然后客户端 2 应该运行该函数。
最好的解决方案是将 DLL 作为单线程运行,但我在互联网上搜索过,我认为这是不可能的。
我已经尝试在互联网上搜索这个问题,并且我想出了一些关于使函数 static
使其线程安全的方法。
我还读到 C++0x 会以某种方式使这个线程安全。但是 MS VC express 不支持它。
我没有多线程方面的经验,所以希望你能提供帮助。提前致谢。
【问题讨论】:
不建议共享这样的 C++ 类。您必须对 std::vector 的特定运行时版本的实现有相当多的了解才能使代码安全,因此通常不要这样做。在大多数情况下,创建一个包装器来访问您的共享内容要安全得多。 这种hackery完全超出了C++的范围,包括C++0x。此外,std::vector<T>
从不是共享data_seg
的一部分。也就是说,number 个元素可能是共享的,但 T
元素的数组本身却不是。您需要编写 shared_allocator
以便正确共享 std::vector<T, shared_allocator>
。这是不平凡的。
【参考方案1】:
此处使用的 Windows API 将是 CreateMutex。创建一个命名的互斥对象。由于需要操作共享数据,请使用互斥量句柄调用 WaitForSingleObject,完成后调用 ReleaseMutex。每个调用 WaitForSingleObject 的线程都获得了互斥锁的所有权,而任何其他调用 WaitForSingleObject 的线程都将停止,直到拥有的线程调用 ReleaseMutex。
当然,我不相信你可以做你想做的事:
-
Dll 可以映射到每个进程空间的不同地址。如果是这样,所有的指针都会不正确。
C++ 不允许对分配进行细粒度控制,并且有许多隐式分配,尤其是在处理 STL 对象时。我不相信您可以获取向量以将所有相关数据存储在共享区域中。
您将不得不使用 C 样式的原始数组来执行此操作。
【讨论】:
Mutex 是否在 Visual Studio Express 中可用?你知道互斥体的任何好例子吗?我在谷歌上找不到任何好的。 整个 windows API 在 Sutdio Express 上可用。不包括 MFC 框架,以及资源编辑器等一些愚蠢的东西。【参考方案2】:看起来您需要一个系统范围的 mutex 来保护您的关键代码部分(不能同时运行的代码)。将函数设为静态与它无关,因为它不会阻止不同的应用程序同时运行它。
【讨论】:
Windows 术语中的“命名互斥锁”。 CreateMutex() 的 lpName 参数。【参考方案3】:我认为Boost.Interprocess 正是您所需要的。它将同时解决同步问题,以及 Jim Brissom 在他的评论中所说的你甚至还没有想到的问题。
【讨论】:
以上是关于DLL 线程安全的主要内容,如果未能解决你的问题,请参考以下文章
安全之路 —— 利用远程线程注入的方法(使用DLL)实现穿墙与隐藏进程