1.以一个C++对象启动一个线程
Q:如何以一个C++成员函数当做线程的起始函数?
错误的例子
正确的做法
为了以一个成员函数启动一个线程,要么使用静态成员函数,要么使用C函数,而非C++成员函数。这两种
技术的本质是相同的,但是静态成员函数的一个优点就是,它能够处理类的private成员变量和protected
成员变量。
由一个成员函数来启动一个线程范例:
这样就可以声明一个String变量,完全可以不了解Critical section,就可以获得同步效果。
----建立抽象的同步化对象
这个析构函数可以被自动调用,而critical section会被自动地解除锁定。绝对不会忘记将critical
section解除锁定。
-------建立可互换的Lock
用安全又简单的“Lock”重写String 类
Q:如何以一个C++成员函数当做线程的起始函数?
错误的例子
#include <windows.h>
#include <stdio.h>
#include <process.h>
typedef unsigned (WINAPI *PBEGINTHREADEX_THREADFUNC)(
LPVOID lpThreadParameter
);
typedef unsigned *PBEGINTHREADEX_THREADID;
class ThreadObject
{
public:
ThreadObject();
void StartThread();
virtual DWORD WINAPI ThreadFunc(LPVOID param);
void WaitForExit();
private:
HANDLE m_hThread;
DWORD m_ThreadId;
};
ThreadObject::ThreadObject()
{
m_hThread = NULL;
m_ThreadId = 0;
}
void ThreadObject::StartThread()
{
m_hThread = (HANDLE)_beginthreadex(NULL,
0,
(PBEGINTHREADEX_THREADFUNC)ThreadFunc,
0,
0,
(PBEGINTHREADEX_THREADID)&m_ThreadId );
if (m_hThread) {
printf("Thread launched\n");
}
}
void ThreadObject::WaitForExit()
{
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
}
DWORD WINAPI ThreadObject::ThreadFunc(LPVOID param) //对类的成员函数默认有一个this参数
{
// Do something useful ...
return 0;
}
void main()
{
ThreadObject obj;
obj.StartThread();
obj.WaitForExit();
}
正确的做法
为了以一个成员函数启动一个线程,要么使用静态成员函数,要么使用C函数,而非C++成员函数。这两种
技术的本质是相同的,但是静态成员函数的一个优点就是,它能够处理类的private成员变量和protected
成员变量。
由一个成员函数来启动一个线程范例:
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>
typedef unsigned (WINAPI *PBEGINTHREADEX_THREADFUNC)(
LPVOID lpThreadParameter
);
typedef unsigned *PBEGINTHREADEX_THREADID;
//
// This ThreadObject is created by a thread
// that wants to start another thread. All
// public member functions except ThreadFunc()
// are called by that original thread. The
// virtual function ThreadMemberFunc() is
// the start of the new thread.
//
class ThreadObject
{
public:
ThreadObject();
void StartThread();
void WaitForExit();
static DWORD WINAPI ThreadFunc(LPVOID param);
protected:
virtual DWORD ThreadMemberFunc();
HANDLE m_hThread;
DWORD m_ThreadId;
};
ThreadObject::ThreadObject()
{
m_hThread = NULL;
m_ThreadId = 0;
}
void ThreadObject::StartThread()
{
m_hThread = (HANDLE)_beginthreadex(NULL,
0,
(PBEGINTHREADEX_THREADFUNC) ThreadObject::ThreadFunc,
(LPVOID)this,
0,
(PBEGINTHREADEX_THREADID) &m_ThreadId );
if (m_hThread) {
printf("Thread launched\n");
}
}
void ThreadObject::WaitForExit()
{
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
}
//
// This is a static member function. Unlike
// C static functions, you only place the static
// declaration on the function declaration in the
// class, not on its implementation.
//
// Static member functions have no "this" pointer,
// but do have access rights.
//
DWORD WINAPI ThreadObject::ThreadFunc(LPVOID param)
{
// Use the param as the address of the object
ThreadObject* pto = (ThreadObject*)param;
// Call the member function. Since we have a
// proper object pointer, even virtual functions
// will be called properly.
return pto->ThreadMemberFunc();
}
//
// This above function ThreadObject::ThreadFunc()
// calls this function after the thread starts up.
//
DWORD ThreadObject::ThreadMemberFunc()
{
// Do something useful ...
return 0;
}
void main()
{
ThreadObject obj;
obj.StartThread();
obj.WaitForExit();
}
在C++中如何利用构造函数和析构函数写一个比较安全的多线程程序,以及如何利用虚函数和多态等性质做
出一个可互换的锁定机制?
在C++中封装一个Critical section
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);
}
在String类中使用CriticalSection类
Class String
{
public:
String();
virtual ~String();
virtual void Set(char *str);
int GetLength();
private:
CriticalSection m_Sync;
char * m_pData;
};
String::String()
{
m_pData=NULL;
}
String::~String()
{
m_Sync.Enter();
delete []m_pData;
m_Sync.Leave();
}
void String::Set(char *str)
{
m_Sync.Enter();
delete [] m_pData;
m_pData=new char[::strlen(str)+1];
::strcpy(m_pData,str);
m_Sync.Leave();
}
int String::GetLength()
{
if(m_pData==NULL)
return 0;
m_Sync.Enter();
int len=::strlen(m_pData);
m_Sync.Leave();
return len;
}
这样就可以声明一个String变量,完全可以不了解Critical section,就可以获得同步效果。
----建立抽象的同步化对象
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);
}
这个析构函数可以被自动调用,而critical section会被自动地解除锁定。绝对不会忘记将critical
section解除锁定。
-------建立可互换的Lock
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);
}
建立一个极安全又简单的Lock
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();
}
上面用C++类取代Win32 API的直接调用
用安全又简单的“Lock”重写String 类
class StringV2
{
public:
StringV2();
virtual ~StringV2();
virtual void Set(char * str);
int getLength();
private:
CriticalSectionV2 m_Lockable;
char * m_pData;
};
StringV2::StringV2()
{
m_pData=NULL;
}
StringV2::~StringV2()
{
delete [] m_pData;
}
void StringV2::Set(char *str)
{
LockV2 localLock(&m_Lockable);
delete [] m_pData;
m_pData=NULL;
m_pData=new char[strlen(str)+1];
strcpy(m_pData,str);
}
int String::GetLength()
{
LockV2 localLock(&m_Lockable);
if(m_pData==NULL)
return 0;
return ::strlen(m_pData);
}