【win32多线程】使用C++编写多线程

1.以一个C++对象启动一个线程
 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);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值