【本章看的比较杂,还是以Q&A的方式展开吧】
Q: C++中调用_beginthreadex()需要注意什么?
A:
unsigned long _beginthreadex(
void *security,
unsigned stack_size,
unsigned (* start_address)(void*),
void *arglist,
unsigned initflag,
unsigned *thrdaddr );
_beginthreadex函数原型的3和6参数类型都为unsigned int,而在CreateThread()这两个参数类型是DWORD(unsigned long),这在32位编译器没区别,C编译器也会忽略,而C++会类型检验,可通过强制类型转换解决此问题
Q: 为什么线程函数不能是C++成员函数?
A:
C++一个非静态的类成员函数都有一个隐藏起来的参数被推入堆栈之中——this
当操作系统启动一个新线程时,它也为该线程产生一个专用的堆栈。操作系统必须在这一新堆栈中重新产生一个对你的线程函数的调用操作。这也就是为什么线程函数的类型一定要符合__cdecl 或 WINAPI(也就是__stacall)的原因。
操作系统只知道把形参放入新堆栈中,而不会放入隐含的this指针。
线程函数要么是静态成员函数,要么是C函数.
static DWORD WINAPI ThreadFunc(LPVOID param);
DWORD WINAPI ThreadFunc(LPVOID param);
Q: 如何利用C++的特性建立安全的临界区CS
A: 利用构造函数和析构函数,
class CriticalSection
{
public:
CriticalSection();
~CriticalSection();
void Enter();
void Leave();
private:
CRITICAL_SECTION m_CritSect;
};
CriticalSection::CriticalSection()
{
InitializeCriticalSection(&m_CritSect);
}
CriticalSection::~CriticalSection()
{
DeleteCriticalSection(&m_CritSect);
}
CriticalSection::Enter()
{
EnterCriticalSection(&m_CritSect);
}
CriticalSection::Leave()
{
LeaveCriticalSection(&m_CritSect);
}
以上四个函数分别完成了初始化、删除、进入、离开的操作,只需创建个对象,无需手动初始化和删除了,使用起来方便了很多,但还不理想,仍需要手动配对调用Enter()和Leave(),仍繁琐,继续改进,
class Lock
{
public:
Lock(CriticalSection* pCritSect);
~Lock();
private:
CriticalSection* m_pCritical;
};
Lock::Lock(CriticalSection* pCritSect)
{
m_pCritical = pCritSect;
EnterCriticalSection(m_pCritical);
}
Lock::~Lock()
{
LeaveCriticalSection(m_pCritical);
}
以上代码不仅可以完成自动初始化和释放,还能自动的解除锁定,完美。
后面本书还讲了一种可互换的Lock,用C++的虚函数虚函数是如何地用来锁定对象而根本不需要知道其真正对象类型是什么。。。【说实话,目前并没有看出这比上面能好用多少,不太懂,如下贴出代码,期待以后回看能理解】
class LockableObject
{
public:
LockableObject() {}
virtual ~ LockableObject(){}
virtual void Lock()=0;
virtual void UnLock()=0;
};
public CriticalSectionV2: public LockableObject
{
CriticalSectionV2();
virtual ~CriticalSectionV2();
virtual void Lock();
virtual void UnLock();
private:
CRITICAL_SECTION m_CritSect;
};
CriticalSectionV2::CriticalSectionV2()
{
InitializeCriticalSection(&m_CritSect);
}
CriticalSectionV2::~CriticalSectionV2()
{
DeleteCriticalSection(&m_CritSect);
}
CriticalSectionV2::Lock()
{
EnterCriticalSection(&m_CritSect);
}
CriticalSectionV2::UnLock()
{
LeaveCriticalSection(&m_CritSect);
}
class LockV2
{
public:
LockV2(LockableObject *pLockable);
~LockV2();
private:
LockableObject * m_pLockable;
};
LockV2::LockV2(LockableObject *pLockable)
{
m_pLockable=pLockable;
m_pLockable->Lock();
}
LockV2::~LockV2()
{
m_pLockable->UnLock();
}