关于多线程调用动态库...当得到合适的答案后,第一时间给分

gccli 2008-12-05 09:18:51
问题是这样的:
  我现在有一个程序,需要调用一个动态库提供的API,当然,这个动态库是别的厂商提供的。
  这个API不是线程安全的,所以,我需要在每个线程调用这个API时加上锁,这样暂时解决了问题。但是,潜在的危机是:多个线程不能并发的调用这个API完成某项工作,不能达到程序最初的目的。
  大家帮我想想,讨论讨论,谢谢。
...全文
291 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
快乐田伯光 2008-12-05
  • 打赏
  • 举报
回复
楼主,你这个问题本身就有问题, 你是想多个线程同时处在某个API调用吗?会有这样的应用?我想不出来?

至于线程不安全API,你可以加一个包裹函数封装成线程安全就可以了,
如:

type fun()
{
lock();
thread_unsage_API();
unlock();
}


[Quote=引用楼主 gccli 的帖子:]
问题是这样的:
  我现在有一个程序,需要调用一个动态库提供的API,当然,这个动态库是别的厂商提供的。
  这个API不是线程安全的,所以,我需要在每个线程调用这个API时加上锁,这样暂时解决了问题。但是,潜在的危机是:多个线程不能并发的调用这个API完成某项工作,不能达到程序最初的目的。
  大家帮我想想,讨论讨论,谢谢。
[/Quote]
Wolf0403 2008-12-05
  • 打赏
  • 举报
回复
对一个 不是线程安全 的接口你希望 多线程并发调用 ?
hhyttppd 2008-12-05
  • 打赏
  • 举报
回复
呵呵,你这个设计是不是有问题,你只要保证短信猫空闲最小,利用率就很高,你判断调用时间做什么?
gccli 2008-12-05
  • 打赏
  • 举报
回复
这是不加临界区的情况,0.4秒,但是会异常退出


Initialized Success!0
Initialized Success!1
CAT1111 Time Spending: 0.634558(s)
CAT0 Time Spending: 0.652624(s)
CAT1111 Time Spending: 0.399149(s)
CAT0 Time Spending: 0.414874(s)
CAT1111 Time Spending: 0.399688(s)
CAT0 Time Spending: 0.412380(s)
...
gccli 2008-12-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 taodm 的回复:]
楼主是怎么看待 单cpu(且单核)下,多线程并发的?是真的在同一时刻有多个线程同时在运行?
[/Quote]

[Quote=引用 11 楼 hhyttppd 的回复:]
呵呵,你加临界区不就是为了想这样吗?
[/Quote]

但是加上临界区后,每个线程调用API的时间变为:0.8秒
Initialized Success!0
Initialized Success!1
CAT0 Time Spending: 0.658266(s)
CAT1111 Time Spending: 1.307721(s)
CAT0 Time Spending: 1.054209(s)
CAT1111 Time Spending: 0.807566(s)
CAT0 Time Spending: 0.805551(s)
CAT1111 Time Spending: 0.804478(s)
CAT0 Time Spending: 0.808760(s)
CAT1111 Time Spending: 0.808193(s)
CAT0 Time Spending: 0.802075(s)
CAT1111 Time Spending: 0.804079(s)
....

这说明什么,多个猫串行了,并没有达到并发调用API的效果。
hhyttppd 2008-12-05
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 gccli 的回复:]
引用 8 楼 hhyttppd 的回复:

就这一部份代码不太可能异常退出吧?


这是两个简单的线程,如果不使用临界区,当并发调用GSMModemSMSReadAll时,就会异常退出。
[/Quote]

你保证两个线程不会同时读一台猫的数据(两个函数各有一个锁)试试看
gccli 2008-12-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 taodm 的回复:]
楼主是怎么看待 单cpu(且单核)下,多线程并发的?是真的在同一时刻有多个线程同时在运行?
[/Quote]

首先我的机器是双核,并不是同一时刻,调用这个API的时间我测过:如下:
大概是0.41秒

////////测试时间的类//////////////
class TimeSpending
{
public:
TimeSpending();
~TimeSpending();

private:
double m_Freq, dfTim;
LARGE_INTEGER m_Frequency;
LONGLONG m_start, m_end;
};

TimeSpending::TimeSpending()
:m_Freq(0.0)
,dfTim(0.0)
{
QueryPerformanceFrequency(&m_Frequency);
m_Freq = (double)m_Frequency.QuadPart;
QueryPerformanceCounter(&m_Frequency);
m_start = m_Frequency.QuadPart;
}

TimeSpending::~TimeSpending()
{
QueryPerformanceCounter(&m_Frequency);
m_end = m_Frequency.QuadPart;
dfTim = (double)(m_end - m_start)/m_Freq;
printf("Time Spending: %lf(s)\n",dfTim);
}

// 猫0的运行线程
DWORD WINAPI cat_run( LPVOID lpParam )
{
LPCRITICAL_SECTION lpCriticalSection = (LPCRITICAL_SECTION) lpParam;
while(true)
{
TimeSpending* ts = new TimeSpending();

EnterCriticalSection(lpCriticalSection);
if(GSMModemIsConn(device0))
{
char* ss = GSMModemSMSReadAll(device0,0);
LeaveCriticalSection(lpCriticalSection);

}
printf("CAT0\t");
delete ts;
ts = NULL;
Sleep(10);
}

return 0;
}
hhyttppd 2008-12-05
  • 打赏
  • 举报
回复
呵呵,你加临界区不就是为了想这样吗?
gccli 2008-12-05
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 hhyttppd 的回复:]
就这一部份代码不太可能异常退出吧?
[/Quote]

这是两个简单的线程,如果不使用临界区,当并发调用GSMModemSMSReadAll时,就会异常退出。
gccli 2008-12-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 hhyttppd 的回复:]
多个线程不能并发的调用这个API完成某项工作

这是什么意思呢?
是仍然不是线程安全呢?
还是其它原因不能工作?
[/Quote]

这个API如上程序(这代码足够简单)所示:就是GSMModemSMSReadAll,只能串行去调用它(这就是我使用临界区的原因),不能并行调用。
hhyttppd 2008-12-05
  • 打赏
  • 举报
回复
就这一部份代码不太可能异常退出吧?
taodm 2008-12-05
  • 打赏
  • 举报
回复
楼主是怎么看待 单cpu(且单核)下,多线程并发的?是真的在同一时刻有多个线程同时在运行?
gccli 2008-12-05
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 Chiyer 的回复:]
如果库不是线程安全的,那你这边怎么改都没用,依然要一个一个通过库的处理

如果是专业的库,你可以查一下它是否有线程安全版
[/Quote]

[Quote=引用 4 楼 xhs_lh04 的回复:]
跟厂商联系,确认是否线程安全,不是唯一方法就是加锁,同步访问,无它,要不就别用多线程,用多进程
[/Quote]

我已经跟厂商联系,还没回复。我也想过用多进程,但是总觉得不太妥当。
gccli 2008-12-05
  • 打赏
  • 举报
回复
他提供的是不透明的,我并不知道是否会有全局变量或其他什么。我的程序是多个短信猫各启一个线程,代码如下:
互斥访问API则没问题,否则异常退出。

DWORD WINAPI cat_run( LPVOID lpParam )
{
LPCRITICAL_SECTION lpCriticalSection = (LPCRITICAL_SECTION) lpParam;
while(true)
{
EnterCriticalSection(lpCriticalSection);
if(GSMModemIsConn(device0))
{
char* ss = GSMModemSMSReadAll(device0,0);
LeaveCriticalSection(lpCriticalSection);
}
printf("CAT0\t");
Sleep(10);
}
return 0;
}

// 猫1的运行线程
DWORD WINAPI cat_run1( LPVOID lpParam )
{
LPCRITICAL_SECTION lpCriticalSection = (LPCRITICAL_SECTION) lpParam;
while(true)
{
EnterCriticalSection(lpCriticalSection);
if(GSMModemIsConn(device1))
{
char* ss = GSMModemSMSReadAll(device1,0);
LeaveCriticalSection(lpCriticalSection);
}

printf("CAT1111\t");
Sleep(10);
}
return 0;
}
xhs_lh04 2008-12-05
  • 打赏
  • 举报
回复
跟厂商联系,确认是否线程安全,不是唯一方法就是加锁,同步访问,无它,要不就别用多线程,用多进程
hhyttppd 2008-12-05
  • 打赏
  • 举报
回复
多个线程不能并发的调用这个API完成某项工作

这是什么意思呢?
是仍然不是线程安全呢?
还是其它原因不能工作?

星羽 2008-12-05
  • 打赏
  • 举报
回复
如果库不是线程安全的,那你这边怎么改都没用,依然要一个一个通过库的处理

如果是专业的库,你可以查一下它是否有线程安全版
hai040 2008-12-05
  • 打赏
  • 举报
回复
好像没办法
除非它的文档明确说明函数是只用到局部变量,还是会用到全局变量或系统资源
这通常都不可能会有
gccli 2008-12-05
  • 打赏
  • 举报
回复
关于guosha 的说法,我有些不解。
好了,讨论就到这吧,无论如何感谢大家的参与。
现在有两件事要做:
1)寄希望厂商的回复,提供线程安全的库。
2)用多进程。但是这样会增加复杂度等问题。
对了,还有一件事,给大家加分。

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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