C++多线程、单例模式
小弟看到网上给的单例模式的实现形式,其中讲到线程安全时,他用JAVA来实现,我想问的是,如果用C++的话,如何确保线程安全啊???
[解决办法]
可以的,你可以参考一下loki的singelton
[解决办法]
好像叫double check
[解决办法]
加锁和double check
http://www.chineselinuxuniversity.net/articles/33508.shtml
[解决办法]
单例线程不安全(只要有类成员变量)
所以单例我一般都不会并行用
[解决办法]
单列线程安全,要双lock
[解决办法]
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include "AutoPtr.h"
#include "Mutex.h"
namespace Tool {
template <typename T>
class Singleton
{
public:
static T* Instance();
protected:
Singleton() { }
~Singleton(){ }
Singleton(const Singleton&);
Singleton& operator= (const Singleton&);
private:
static AutoPtr<T> instance_;
static Mutex mutex_;
};
template <typename T>
AutoPtr<T> Singleton<T>::instance_;
template <typename T>
Mutex Singleton<T>::mutex_;
template <typename T>
inline T* Singleton<T>::Instance()
{
if (instance_.Get() == 0) {
Guard<Mutex> guard(mutex_);
if (instance_.Get() == 0)
instance_.Reset(new T());
}
return instance_.Get();
}
};
#endif
#ifndef _GUARD_H_
#define _GUARD_H_
#include <pthread.h>
#include <assert.h>
#include "NonCopyable.h"
// namespace Tool {
class Mutex : public NonCopyable {
public:
Mutex();
~Mutex();
void Lock();
int TryLock();
void UnLock();
private:
pthread_mutex_t mutex_;
};
inline Mutex::Mutex()
{
assert (::pthread_mutex_init(&mutex_, 0) == 0);
}
inline Mutex::~Mutex()
{
assert (::pthread_mutex_destroy(&mutex_) == 0);
}
inline void Mutex::Lock()
{
assert (::pthread_mutex_lock(&mutex_) == 0);
}
inline int Mutex::TryLock()
{
return ::pthread_mutex_trylock(&mutex_) == 0;
}
inline void Mutex::UnLock()
{
assert (::pthread_mutex_unlock(&mutex_) == 0);
}
template <typename Lock>
class Guard : public NonCopyable {
public:
explicit Guard(Lock& mutex);
~Guard();
private:
Lock& mutex_;
};
template <typename Lock>
inline Guard<Lock>::Guard(Lock& mutex)
: mutex_(mutex)
{
mutex_.Lock();
}
template <typename Lock>
Guard<Lock>::~Guard()
{
mutex_.UnLock();
}
// };
#endif
#ifndef _AUTO_PTR_H_
#define _AUTO_PTR_H_
namespace Tool {
template <typename T>
class AutoPtr {
public:
explicit AutoPtr(T* ptr = 0);
AutoPtr(AutoPtr<T>& rhs);
template<typename U>
AutoPtr(AutoPtr<U>& rhs);
~AutoPtr();
AutoPtr<T>& operator =(AutoPtr<T>& rhs);
T* operator ->() const;
T& operator *() const;
T* Get() const;
void Reset(T* ptr = 0);
T* Release();
private:
T* ptr_;
};
template <typename T>
inline AutoPtr<T>::AutoPtr(T* ptr)
: ptr_(ptr)
{ }
template <typename T>
template <typename U>
inline AutoPtr<T>::AutoPtr(AutoPtr<U>& rhs)
: ptr_(rhs.Release())
{ }
template <typename T>
AutoPtr<T>::~AutoPtr()
{
delete ptr_;
ptr_ = 0;
}
template <typename T>
inline AutoPtr<T>& AutoPtr<T>::operator= (AutoPtr<T>& rhs)
{
if (this == &rhs)
return *this;
Reset(rhs.Release());
return *this;
}
template<typename T>
inline T* AutoPtr<T>::operator-> () const
{
return ptr_;
}
template<typename T>
inline T& AutoPtr<T>::operator* () const
{
return *ptr_;
}
template<typename T>
inline T* AutoPtr<T>::Get() const
{
return ptr_;
}
template<typename T>
inline void AutoPtr<T>::Reset(T* ptr)
{
if (ptr_ != ptr) {
delete ptr_;
ptr_ = ptr;
}
}
template<typename T>
inline T* AutoPtr<T>::Release()
{
T* pT = ptr_;
ptr_ = 0;
return pT;
}
};
#endif
//Singleton.h
#pragma once
class CSingleton
{
CSingleton(void);
public:
static CSingleton& GetInstance();
~CSingleton(void);
void AssureInitialized();//保证本单件对象初初始化完毕
private:
boolm_bHasInitialized;//初始化完了吗?
};
//Singleton.cpp
#include "Singleton.h"
#include <windows.h>
#include <cstdio>
CSingleton::CSingleton(void)
{
printf( "** begin CSingleton()\n" );
Sleep( 4000 );//only for test
//在这里添加成员变量的初始化代码
printf( "** end CSingleton()\n" );
m_bHasInitialized = true;
}
CSingleton::~CSingleton(void)
{
}
//static CSingleton instance;这行代码分为两步,第一步是给instance对象分配内存,
//第二步是instance调用其构造函数,对本对象的成员进行初始始化工作.第一步是一个原子
//操作,不会被打断,且只执行一次,但执行到第二步时,有可能让出了CPU,假设这时另一个
//线程调用了CSingleton::GetInstance()函数,那么就返回一个未初始化instance对象.
//instance.AssureInitialized()可保证这件事不会发声.因为instance是一个静态变量,
//它的成员m_bHasInitialized也是静态变量,静态变量在分配内存时就会被初始化为0
//即m_bHasInitialized的初值是false, 所以只有当第一个进行GetInstance()函数的线程执行会
//构造函数后,其它调用GetInstance()的线程才有可以往下执行,故这个单件是多线程安全的.
//不管你们信不信,反正我是做过测试验证的.也欢迎大家提出意见.
CSingleton& CSingleton::GetInstance()
{
static CSingleton instance;
instance.AssureInitialized();
printf( "return instance\n" );
return instance;
}
void CSingleton::AssureInitialized()
{
while( !m_bHasInitialized )
Sleep( 0 );
}
//main.cpp
#include "Singleton.h"
#include <windows.h>
#include <cstdio>
#include <cstdlib>
#define THREAD_NUM50
HANDLE g_hThreads[THREAD_NUM] = {0};
unsigned long __stdcall ThreadFun( void * pParam )
{
CSingleton::GetInstance();
return 0;
}
void main()
{
for( int i = 0; i < THREAD_NUM; ++i )
g_hThreads[i] = CreateThread( NULL, 0, ThreadFun, NULL, 0, NULL );
WaitForMultipleObjects( THREAD_NUM, g_hThreads, TRUE, INFINITE );
system( "pause" );
}