一个dll,大致结构如下:
一全局变量:g_ggg;
一个套节字重叠IO使用的回调函数(完成例程);
一个线程;
若干个导出方法。
uint g_ggg;
void CALLBACK CompletionROUTINE(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
{
//使用g_ggg,包括读写
...
}unsigned int __stdcall WorkThread(void* pVoid)
{
//使用g_ggg,包括读写
WSASend(..., CompletionROUTINE);
}dllexport void fun1()
{
//使用g_ggg,包括读写
}dllexport void fun2()
{
//使用g_ggg,包括读写
}
语法不一定正确,大家明白意思即可。现在我的问题是,有什么办法对g_ggg互斥最好,要求速度第一,麻烦一点都不在乎。
另外提一点,对g_ggg访问的地方很多,不止上面提到的那几处。
一全局变量:g_ggg;
一个套节字重叠IO使用的回调函数(完成例程);
一个线程;
若干个导出方法。
uint g_ggg;
void CALLBACK CompletionROUTINE(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
{
//使用g_ggg,包括读写
...
}unsigned int __stdcall WorkThread(void* pVoid)
{
//使用g_ggg,包括读写
WSASend(..., CompletionROUTINE);
}dllexport void fun1()
{
//使用g_ggg,包括读写
}dllexport void fun2()
{
//使用g_ggg,包括读写
}
语法不一定正确,大家明白意思即可。现在我的问题是,有什么办法对g_ggg互斥最好,要求速度第一,麻烦一点都不在乎。
另外提一点,对g_ggg访问的地方很多,不止上面提到的那几处。
// CDataClass.h 头文件#include "afxmt.h"class CDataClass
{
public:
CDataClass();
~CDataClass(); void SetData(xxxx); UINT operator=() const;private:
UINT g_ggg;
CMutex m_hMutex;
};
在类中的 SetData 成员函数中,使用 CMutex 类
// CDataClass.h 代码void CDataClass::SetData(xxxx)
{
m_hMutex.Lock();
// 这里进行数据写操作
m_hMutex.Unlock();
}UINT CDataClass::operator=() const
{
return g_ggg;
}大致这样吧,等其他高人补充~
然后直接对类进行操作~
我想这样是最方便的了~至于速度嘛,因为要同步,所以……
按以上做法,逻辑上还存在一个问题:有读操作正在进行,写操作正在等待信号量的引用计数为0,这时又有新的读操作发生,这个的读操作就又进入了,极限情况,不断有读操作发生,信号量的引用计数一直就不能为0,导致写操作一直等待。也就是在这种情况下,读操作优先权更大了,不平等竞争。
LZ考虑一下这种情况现实是否会发生,如果会,那就需要再次基础上再增加逻辑。再增加的逻辑,
再设计一个Event2,初始有信号,写操作进入等待Event和信号量前,先把Event2设为无信号,等待成功后马上将Event2设为有信号。读操作不设置Event2的信号状态,只是等待event之前先等待Event2。
g_ggg++;
LeaveCriticalSection(&crs);这样速度如何?
只是示例,我对g_ggg的修改不光是++和--,主要是位运算。
那么读的时候就直接读。写的时候用 _InterlockedExchange( &g_ggg, newValue );
PS: #include <intrin.h>_InterlockedExchanger的底层实现是对xchg指令加上lock前缀,执行的时候会锁住总线,只能有一个CPU访问内存,且为原子指令,效率极高……
这样就不能并发读了。
因为如果有两个线程同时读,并且一个线程把g_ggg加1并写回,另一个线程也是如此,那么g_ggg最终只加了1而不是2。
楼主对于什么时候能并发读,再考虑一下吧。要实现你说的“根据其内容来决定是否要写g_ggg”,就不能并发读,而要用临界区或互斥量。
EnterCriticalSection( cs );
if( CanWrite( g_ggg ) )
{
g_ggg = xxx;
}
LeaveCriticalSection( cs );
这是唯一正确的办法。