C++多个线程调用同一个dll中的一个函数,怎么知道有多少个线程同时进入了这个函数体

yidaimu 2014-08-08 10:18:09
C++多个线程调用同一个dll中的一个函数,但是要求这个函数同一时刻只能被有限个线程调用。因为这个函数使用了一些有限资源,当资源不够时,希望该函数直接返回。dll函数是用“C”方式导出的。抱歉,没多少分了,拜谢各位大神。
...全文
792 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
nemo2011 2016-09-21
  • 打赏
  • 举报
回复
HANDLE CreateSemaphore( 
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, 
                       // pointer to security attributes 
  LONG lInitialCount,  // initial count 
  LONG lMaximumCount,  // maximum count 
  LPCTSTR lpName       // pointer to semaphore-object name 
); 
用Semaphore控制线程访问的个数。
「已注销」 2014-08-08
  • 打赏
  • 举报
回复
引用 15 楼 truexf 的回复:
有限的访问是同时只允许一个线程调用?还是可以允许有限的n个调用?
如果是前者,用临界区控制。如果是后者,用信号量控制。 以上建议只针对windows平台。
「已注销」 2014-08-08
  • 打赏
  • 举报
回复
有限的访问是同时只允许一个线程调用?还是可以允许有限的n个调用?
justin_duan 2014-08-08
  • 打赏
  • 举报
回复
引用 10 楼 yidaimu 的回复:
[quote=引用 5 楼 justin_duan 的回复:] [quote=引用 3 楼 yidaimu 的回复:] 感谢您的回答。其实我在dll内部定义了一个static变量a=0,函数中打印++a的结果都是1。也就是没有达到计数的效果。有限资源的个数是dll控制的,所以没有采用在外部调用时限制线程的个数这种方式。这实际上像是一个子线程不通过父线程控制而达到同步的问题。
外部资源有源码吗?如果可以的话是不是能从外部资源控制一下访问数。 PS:打印++a说明当前时间函数也许没被调用啊- -怎么就确定是没计数效果呢,能否考虑做这么个试验,把DLL的函数修改下一直while(1)循环不结束函数再看看a的结果,我觉得在函数内设置一个static变量应该是有效的。 另外我猜你这个问题的需求应该是不想用临界区的,如果不用临界区处理的话我觉得最好还是能在调用端处理对dll的调用,省点心[/quote] 不是不想用临界区,是这个临界区需要dll(作为子线程)自己去维护。或者说有什么办法能让外部程序来维护这个临界区? 另外,我之前++a在代码中写错地方了。我测试的结果是++a会是1-N(顺序不是递增,但数字不重复)。我还是有点担心数字会重复,毕竟我没有对++a做Lock操作。[/quote] 用mutex试试看?可以跨进程同步。我主要是没太搞明白你说的外部资源,是一个还是多个进程。
赵4老师 2014-08-08
  • 打赏
  • 举报
回复
Critical Section Objects Critical section objects provide synchronization similar to that provided by mutex objects, except that critical section objects can be used only by the threads of a single process. Event, mutex, and semaphore objects can also be used in a single-process application, but critical section objects provide a slightly faster, more efficient mechanism for mutual-exclusion synchronization. Like a mutex object, a critical section object can be owned by only one thread at a time, which makes it useful for protecting a shared resource from simultaneous access. There is no guarantee about the order in which threads will obtain ownership of the critical section, however, the system will be fair to all threads. The process is responsible for allocating the memory used by a critical section. Typically, this is done by simply declaring a variable of type CRITICAL_SECTION. Before the threads of the process can use it, initialize the critical section by using the InitializeCriticalSection or InitializeCriticalSectionAndSpinCount function. A thread uses the EnterCriticalSection or TryEnterCriticalSection function to request ownership of a critical section. It uses the LeaveCriticalSection function to release ownership of a critical section. If the critical section object is currently owned by another thread, EnterCriticalSection waits indefinitely for ownership. In contrast, when a mutex object is used for mutual exclusion, the wait functions accept a specified time-out interval. The TryEnterCriticalSection function attempts to enter a critical section without blocking the calling thread. Once a thread owns a critical section, it can make additional calls to EnterCriticalSection or TryEnterCriticalSection without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section that it already owns. To release its ownership, the thread must call LeaveCriticalSection once for each time that it entered the critical section. A thread uses the InitializeCriticalSectionAndSpinCount or SetCriticalSectionSpinCount function to specify a spin count for the critical section object. On single-processor systems, the spin count is ignored and the critical section spin count is set to 0. On multiprocessor systems, if the critical section is unavailable, the calling thread will spin dwSpinCount times before performing a wait operation on a semaphore associated with the critical section. If the critical section becomes free during the spin operation, the calling thread avoids the wait operation. Any thread of the process can use the DeleteCriticalSection function to release the system resources that were allocated when the critical section object was initialized. After this function has been called, the critical section object can no longer be used for synchronization. When a critical section object is owned, the only other threads affected are those waiting for ownership in a call to EnterCriticalSection. Threads that are not waiting are free to continue running.
赵4老师 2014-08-08
  • 打赏
  • 举报
回复
纠正楼上: 临界区虽然不是跨进程的,但效率一般高于其它同步机制。
赵4老师 2014-08-08
  • 打赏
  • 举报
回复
临界区是跨进程的,且效率一般高于其它同步机制。 Synchronization Functions The following functions are used in synchronization. CancelWaitableTimer CreateEvent CreateMutex CreateSemaphore CreateWaitableTimer DeleteCriticalSection EnterCriticalSection GetOverlappedResult InitializeCriticalSection InitializeCriticalSectionAndSpinCount InterlockedCompareExchange InterlockedDecrement InterlockedExchange InterlockedExchangeAdd InterlockedIncrement LeaveCriticalSection MsgWaitForMultipleObjects MsgWaitForMultipleObjectsEx OpenEvent OpenMutex OpenSemaphore OpenWaitableTimer PulseEvent QueueUserAPC ReleaseMutex ReleaseSemaphore ResetEvent SetCriticalSectionSpinCount SetEvent SetWaitableTimer SignalObjectAndWait TimerAPCProc TryEnterCriticalSection WaitForMultipleObjects WaitForMultipleObjectsEx WaitForSingleObject WaitForSingleObjectEx
yidaimu 2014-08-08
  • 打赏
  • 举报
回复
引用 5 楼 justin_duan 的回复:
[quote=引用 3 楼 yidaimu 的回复:] 感谢您的回答。其实我在dll内部定义了一个static变量a=0,函数中打印++a的结果都是1。也就是没有达到计数的效果。有限资源的个数是dll控制的,所以没有采用在外部调用时限制线程的个数这种方式。这实际上像是一个子线程不通过父线程控制而达到同步的问题。
外部资源有源码吗?如果可以的话是不是能从外部资源控制一下访问数。 PS:打印++a说明当前时间函数也许没被调用啊- -怎么就确定是没计数效果呢,能否考虑做这么个试验,把DLL的函数修改下一直while(1)循环不结束函数再看看a的结果,我觉得在函数内设置一个static变量应该是有效的。 另外我猜你这个问题的需求应该是不想用临界区的,如果不用临界区处理的话我觉得最好还是能在调用端处理对dll的调用,省点心[/quote] 不是不想用临界区,是这个临界区需要dll(作为子线程)自己去维护。或者说有什么办法能让外部程序来维护这个临界区? 另外,我之前++a在代码中写错地方了。我测试的结果是++a会是1-N(顺序不是递增,但数字不重复)。我还是有点担心数字会重复,毕竟我没有对++a做Lock操作。
赵4老师 2014-08-08
  • 打赏
  • 举报
回复
在DllMain中 fdwReason 为DLL_PROCESS_ATTACH时InitializeCriticalSection 为DLL_PROCESS_DETACH时DeleteCriticalSection
yidaimu 2014-08-08
  • 打赏
  • 举报
回复
引用 4 楼 zhao4zhong1 的回复:
CRITICAL_SECTION cs;

InitializeCriticalSection(&cs);

int Limit4ThreadCalled() {
    static DWORD ThreadIDs[4];
    int it;
    DWORD tid;
    EnterCriticalSection(&cs);
    tid=GetCurrentThreadId(VOID);
    for (it=0;it<4;it++) {
        if (ThreadIDs[it]==tid) break;
        if (ThreadIDs[it]==0) {
            ThreadIDs[it]=tid;
            break;
        }
    }
    LeaveCriticalSection(&cs);
    if (it>=4) return 1;
    //...

    EnterCriticalSection(&cs);
    ThreadIDs[it]=0;
    LeaveCriticalSection(&cs);
    return 0;
}

DeleteCriticalSection(&cs);
CritialSection的初始化和释放的时机怎么控制呢?dll导出的只是一个函数(dll内部可以使用全局或是静态变量),不能在外部控制初始化和释放CritialSection吧。
勤奋的小游侠 2014-08-08
  • 打赏
  • 举报
回复
引用 3 楼 yidaimu 的回复:
感谢您的回答。其实我在dll内部定义了一个static变量a=0,函数中打印++a的结果都是1。也就是没有达到计数的效果。有限资源的个数是dll控制的,所以没有采用在外部调用时限制线程的个数这种方式。这实际上像是一个子线程不通过父线程控制而达到同步的问题。
函数内部有static变量的,是不能重入的,即不能够用于多线程。因为二个线程同时让static 变量++。这样的结果是不确定的。并不能够++2次。
angel_su 2014-08-08
  • 打赏
  • 举报
回复
信号量Semaphore...
justin_duan 2014-08-08
  • 打赏
  • 举报
回复
引用 3 楼 yidaimu 的回复:
感谢您的回答。其实我在dll内部定义了一个static变量a=0,函数中打印++a的结果都是1。也就是没有达到计数的效果。有限资源的个数是dll控制的,所以没有采用在外部调用时限制线程的个数这种方式。这实际上像是一个子线程不通过父线程控制而达到同步的问题。
外部资源有源码吗?如果可以的话是不是能从外部资源控制一下访问数。 PS:打印++a说明当前时间函数也许没被调用啊- -怎么就确定是没计数效果呢,能否考虑做这么个试验,把DLL的函数修改下一直while(1)循环不结束函数再看看a的结果,我觉得在函数内设置一个static变量应该是有效的。 另外我猜你这个问题的需求应该是不想用临界区的,如果不用临界区处理的话我觉得最好还是能在调用端处理对dll的调用,省点心
赵4老师 2014-08-08
  • 打赏
  • 举报
回复
CRITICAL_SECTION cs;

InitializeCriticalSection(&cs);

int Limit4ThreadCalled() {
    static DWORD ThreadIDs[4];
    int it;
    DWORD tid;
    EnterCriticalSection(&cs);
    tid=GetCurrentThreadId(VOID);
    for (it=0;it<4;it++) {
        if (ThreadIDs[it]==tid) break;
        if (ThreadIDs[it]==0) {
            ThreadIDs[it]=tid;
            break;
        }
    }
    LeaveCriticalSection(&cs);
    if (it>=4) return 1;
    //...

    EnterCriticalSection(&cs);
    ThreadIDs[it]=0;
    LeaveCriticalSection(&cs);
    return 0;
}

DeleteCriticalSection(&cs);
yidaimu 2014-08-08
  • 打赏
  • 举报
回复
感谢您的回答。其实我在dll内部定义了一个static变量a=0,函数中打印++a的结果都是1。也就是没有达到计数的效果。有限资源的个数是dll控制的,所以没有采用在外部调用时限制线程的个数这种方式。这实际上像是一个子线程不通过父线程控制而达到同步的问题。
707wk 2014-08-08
  • 打赏
  • 举报
回复
引用 1 楼 mgy4938 的回复:
定义个全局变量了,记一下数
当创建一个新线程的时候用一个变量来计数
nextseconds 2014-08-08
  • 打赏
  • 举报
回复
定义个全局变量了,记一下数
赵4老师 2014-08-08
  • 打赏
  • 举报
回复
引用 22 楼 go_and_see 的回复:
[quote=引用 12 楼 zhao4zhong1 的回复:] 纠正楼上: 临界区虽然不是跨进程的,但效率一般高于其它同步机制。
哈哈,赵老师差点毁了俺的三观,好好及时纠正过来。 [/quote]
边走边瞧 2014-08-08
  • 打赏
  • 举报
回复
引用 12 楼 zhao4zhong1 的回复:
纠正楼上: 临界区虽然不是跨进程的,但效率一般高于其它同步机制。
哈哈,赵老师差点毁了俺的三观,好好及时纠正过来。
PeiS0927 2014-08-08
  • 打赏
  • 举报
回复
既然是C++,那就在dll导出类里定义一个静态数据成员吧,这样不是很好吗?不要写全局变量,因为你做的是C++而不是C。
加载更多回复(4)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧