首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C++多线程、单例模式解决办法

2013-12-06 
C++多线程、单例模式小弟看到网上给的单例模式的实现形式,其中讲到线程安全时,他用JAVA来实现,我想问的是,

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" );
}

大家可以把程序拷到编译器中去跑一下啊

热点排行