同一DLL中的两个函数可以由两个线程调用吗

Can two functions in same DLL be called by two threads?

本文关键字:两个 线程 调用 同一 DLL 函数      更新时间:2023-10-16

我用Visual C++2008编写了一个DLL MyDLL.DLL,如下所示:

(1) MFC静态链接(2) 使用多线程运行库。

在DLL中,这是由两个导出函数共享的全局数据m_data,如下所示:

    ULONGLONG WINAPI MyFun1(LPVOID *lpCallbackFun1)
    {
        ...
        Write m_Data(using Critical section to protect)
        …
        return  xxx;
    }
    ULONGLONG WINAPI MyFun2(LPVOID *lpCallbackFun2)
    {
        ...
        Suspend MyThread1 to prevent conflict.
        Read m_Data(using Critical section to protect)
        Resume MyThread1.
        …
        return  xxx;
    }

在我的主应用程序中,它将首先调用LoadLibrary加载MyDLL.dll,然后获取MyFun1和MyFun2的地址,然后执行以下操作:

(1) 启动一个新线程MyThread1,它将调用MyFun1来完成一项耗时的任务。(2) 启动一个新线程MyThread2,它将多次调用MyFun2,如下所示:

    for (nIndex = 0; nIndex = 20; nIndex)
    {
    nResult2 = MyFun2(lpCallbackFun2);
    NextStatement2; 
    }

尽管MyThread1和MyThread2使用关键部分来保护共享数据m_data,但我仍然会在访问共享数据之前挂起MyThread1,以防止任何可能的冲突。

问题是:

(1) 当第一次调用MyFun2时,一切正常,MyFun2的返回值(即nResult2)为1,这是预期的。(2) 当第二次、第三次和第四次调用MyFun2时,MyFun2中的操作执行成功,但MyFun2的返回值(即nResult2)是随机值,而不是期望值1。我尝试使用Debug跟踪MyFun2,并确认最后一条返回语句只是返回一个值1,但调用程序在检查nResult2时会收到一个随机值,而不是1。(3) 在第四次调用MyFun2并返回到MyFun2之后的下一条语句之后,无论下一条是什么语句,我都会得到一个"检测到缓冲区溢出"错误

我认为这看起来像是堆栈损坏,所以试着做一些测试:

  1. 我确认编译器中的/GS(堆栈安全检查)功能已打开
  2. 如果在MyThread1中的MyFun1完成后调用MyFun2,那么一切都会正常
  3. 在调试模式下,MyFun2中读取共享数据m_data的代码行不会导致任何错误或异常。MyFun1中写入共享数据的代码行也不会

那么,如何解决这个问题

谢谢!

我想在这一行

Suspend MyThread1 to prevent conflict.

您正在使用SuspendThread()函数。这就是它的文件所说的:

此函数主要设计用于调试器它不用于线程同步。如果调用线程试图获取挂起线程所拥有的同步对象,则在拥有同步对象(如互斥对象或关键节)的线程上调用SuspendThread可能会导致死锁。为了避免这种情况,应用程序中不是调试器的线程应该向另一个线程发出挂起自身的信号。目标线程必须设计为监视此信号并做出适当的响应

所以,简而言之:不要使用它。关键部分和其他同步对象的工作做得很好。

永远不要使用SupsendThread!!!从来没有!SuspendThread仅用于调试目的。

原因很简单。你不知道挂起线程的位置。当线程阻塞了您想要使用的资源时,这可能正是时候。还有一堆CRT函数使用线程同步。只需使用标准扇区或互斥。

只需查看此处的简单示例:http://blog.kalmbachnet.de/?postid=6在这里http://blog.kalmbachnet.de/?postid=16

由于这是一个windows程序,在读取或写入共享数据时,您可以使用基于windows的互斥或信号量以及WaitForSingleObject。