C++ 场景:多线程应用程序使用的DLL中的全局变量

C++ 场景:多线程应用程序使用的DLL中的全局变量,c++,multithreading,global-variables,mutex,critical-section,C++,Multithreading,Global Variables,Mutex,Critical Section,几个月前,我在orkut遇到了一个家伙问我的这个有趣的场景。虽然,我提出了一个解决这个问题的非可移植解决方案,并用小代码对其进行了测试,但我仍然想知道你们有什么要说和建议 假设,我创建了一个DLL,导出了一些功能,用C++编写,用于单线程客户端。这个DLL声明了许多全局变量,有些可能是只读的常量变量,有些是可修改的 不管怎么说,后来情况发生了变化,现在我希望同一个DLL能够在不修改DLL的情况下处理多线程应用程序;这意味着,多个线程从DLL访问函数和全局变量,并修改它们。。等等所有这些都可能导致

几个月前,我在orkut遇到了一个家伙问我的这个有趣的场景。虽然,我提出了一个解决这个问题的非可移植解决方案,并用小代码对其进行了测试,但我仍然想知道你们有什么要说和建议

假设,我创建了一个DLL,导出了一些功能,用C++编写,用于单线程客户端。这个DLL声明了许多全局变量,有些可能是只读的常量变量,有些是可修改的

不管怎么说,后来情况发生了变化,现在我希望同一个DLL能够在不修改DLL的情况下处理多线程应用程序;这意味着,多个线程从DLL访问函数和全局变量,并修改它们。。等等所有这些都可能导致全局变量包含不一致的值

所以问题是,


我们能在客户端代码中做些什么来防止对DLL的多次访问,同时确保每个线程在其自身的上下文中运行吗?这意味着,当它访问DLL时,DLL的全局值与以前相同?

当然,您始终可以创建一个包装层来处理多线程特定的任务,例如锁定。您甚至可以在与原始DLL链接的第二个DLL中执行此操作,然后将最终项目链接到该新DLL

请注意,无论您如何实现它,这都不是一项容易的任务。您必须准确地知道哪个线程能够在什么时候修改哪个值,谁能够读取什么以及何时读取等等,除非您想遇到死锁或竞争条件等问题

如果您的解决方案允许,通常最好分配一个线程来修改任何数据,并让所有其他线程都只是读取而从不写入,因为并发读取访问总是比并发写入访问提供所有基本功能更容易实现,例如

我们能在客户端代码中做些什么来防止对DLL的多次访问,同时确保每个线程在其自身的上下文中运行吗?这意味着,当它访问DLL时,DLL的全局值与以前相同

这是最难的部分。我认为top实现这一点的唯一方法是围绕现有DLL创建一个包装器。调用它时,它将还原当前线程的状态全局变量,并在DLL调用返回时保存它们。您需要知道DLL中的所有状态变量,并能够读/写它们


如果性能不是问题,那么对整个DLL使用一个锁就足够了,而且是最容易正确实现的。这将确保一次只有一个线程访问或写入DLL。

如果至少允许您重建DLL,则可以将declspecthreadlocal添加到所有全局定义中。我强烈怀疑这会在任何具有构造函数或析构函数的静态作用域类对象上失败。。。不,我们无法将uu declspecthreadlocal添加到全局,因为不允许修改源代码:-Mephane,你的最后一段很有意义,事实上我在我的解决方案中做了类似的事情,但没有使用Boost API。顺便说一下,谢谢您的回复-顺便问一下,您是否意识到,对于不同的线程,globals的值很可能会有所不同,因此,每当一个线程在锁定其他线程的同时访问DLL时,它应该具有与以前相同的globals值,这意味着当前线程必须从相同的点/状态运行。对不起,我忘了问您,Boost API是否为不同的线程和所有线程处理不同的值?在前面的评论中解释了这一点?@Nawaz:这使情况变得复杂,不是吗?如果您的dll是状态完整的,那么如果不修改代码,您的任务似乎很难实现。您需要每线程存储,或者修改接口以使其支持每客户端会话。@Nawaz:为什么全局的值应该不同,除非某些线程修改它们?如果您希望每个线程都获得该数据的“原始”副本,那么无论如何,您都可以使用该原始、未更改数据的副本启动所有线程。然而,当您确实希望多线程访问同一数据时,就会出现当前的问题,即多线程访问同一数据的身份,而不是值相等。还是我误解了你的问题?