什么是单例模式
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例
其中单例模式的具体实现如下:
饿汉形式——当类被加载的时候便进行初始化单例对象
直接在加载后初始化
#include <iostream>
#include <pthread.h>
using namespace std;
pthread_mutex_t mutex;
class Singleton
{
private:
static Singleton *mInstance;
static int handlecount;
private:
Singleton()
{
}
public:
static Singleton *GetInstance()
{
/*
if(NULL == mInstance)
{
usleep(100000);
mInstance = new Singleton;
}
*/
handlecount ++;
return mInstance;
}
static int Gethandlecount()
{
return handlecount;
}
void release()
{
handlecount --;
if(handlecount == 0 && mInstance != NULL)
{
delete mInstance;
cout << "释放成功" << endl;
}
}
};
Singleton *Singleton::mInstance = new Singleton;
int Singleton::handlecount = 0;
void *createl(void *arg)
{
//pthread_mutex_lock(&mutex);
Singleton *s1 = Singleton::GetInstance();
cout << s1 << endl;
//pthread_mutex_unlock(&mutex);
}
int main(int argc, char **argv)
{/*
Singleton *s1 = Singleton::GetInstance();
Singleton *s2 = Singleton::GetInstance();
Singleton *s3 = Singleton::GetInstance();
Singleton *s4 = Singleton::GetInstance();
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
if(s1 == s2)
{
cout << "对象相同" << endl;
}
else
{
cout << Singleton::Gethandlecount() << endl;
}
cout << Singleton::Gethandlecount() << endl;
s1 -> release();
s2 -> release();
s3 -> release();
s4 -> release();
cout << Singleton::Gethandlecount() << endl;
*/
pthread_t pthread_id[20];
void *val;
//pthread_mutex_init(&mutex,NULL);
for(int i = 0;i < 20;i++)
{
pthread_create(&pthread_id[i],NULL,createl,NULL);
}
for(int i = 0;i < 20;i++)
{
pthread_join(pthread_id[i],&val);
}
//pthread_mutex_destroy(&mutex);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
懒汉形式——当需要使用单例对象时进行初始化操作(多版本)
版本1:
public class SingleDemo{
private static SingleDemo demo = null;
private SingleDemo(){}
public static SingleDemo getDemo(){
if(demo == null){
demo = new SingleDemo();
}
return demo;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
这是最简单的版本,但是有个致命的问题就是,它不是一个线程安全的例子,也就是说在多线程环境下,并不总能保证单例。
版本2:
public class SingleDemo{
private static SingleDemo demo = null;
private SingleDemo(){}
public synchronized static SingleDemo getDemo(){
if(demo == null){
demo = new SingleDemo();
}
return demo;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
通过对方法上锁,实现的线程安全的获取单例的操作,但是很遗憾,因为这个方法在绝大多数情况下是不需要同步的,加锁严重降低了程序执行的效率,所以不提倡使用。
版本3:
public class SingleDemo{
private static SingleDemo demo = null;
private SingleDemo(){}
public static SingleDemo getDemo(){
if(demo == null){
synchronized(SingleDemo.class) {
demo = new SingleDemo();
}
}
return demo;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
对版本2进行优化后,可以明显提高程序的效率,但是很遗憾,这段代码并不能保证线程安全。
版本4:
public class SingleDemo{
private static SingleDemo demo = null;
private SingleDemo(){}
public static SingleDemo getDemo(){
if(demo == null){
synchronized(SingleDemo.class) {
if(demo == null) {
demo = new SingleDemo();
}
}
}
return demo;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
这是上述版本的最终形态,俗称双检锁模式,通过双重校验,达到了线程安全的目的,同时避免了代码频繁上锁解锁的过程。
版本5:
public class SingleDemo{
private SingleDemo(){}
private static class Singleton{
private static final SingleDemo DEMO = new SingleDemo();
}
public static SingleDemo getDemo(){
return Singleton.DEMO;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
这样至少看起来代码简洁不少,不仅达到了懒加载的效果,还实现了线程安全。
版本6:
public enum SingleDemo{
DEMO;
public static SingleDemo getDemo(){
return DEMO;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
最后这种是通过枚举实现的单例,但是现实用到的不多,该模式为Effective Java作者Josh Bloch 所推崇,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象(如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例)。
#include <iostream>
#include <pthread.h>
using namespace std;
pthread_mutex_t mutex;
class Singleton
{
private:
static Singleton *mInstance;
static int handlecount;
private:
Singleton()
{
}
public:
static Singleton *GetInstance()
{
if(NULL == mInstance)
{
usleep(100000);
mInstance = new Singleton;
}
handlecount ++;
return mInstance;
}
static int Gethandlecount()
{
return handlecount;
}
void release()
{
handlecount --;
if(handlecount == 0 && mInstance != NULL)
{
delete mInstance;
cout << "释放成功" << endl;
}
}
};
Singleton *Singleton::mInstance = NULL;
int Singleton::handlecount = 0;
void *createl(void *arg)
{
pthread_mutex_lock(&mutex);
Singleton *s1 = Singleton::GetInstance();
cout << s1 << endl;
pthread_mutex_unlock(&mutex);
}
int main(int argc, char **argv)
{/*
Singleton *s1 = Singleton::GetInstance();
Singleton *s2 = Singleton::GetInstance();
Singleton *s3 = Singleton::GetInstance();
Singleton *s4 = Singleton::GetInstance();
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
if(s1 == s2)
{
cout << "对象相同" << endl;
}
else
{
cout << Singleton::Gethandlecount() << endl;
}
cout << Singleton::Gethandlecount() << endl;
s1 -> release();
s2 -> release();
s3 -> release();
s4 -> release();
cout << Singleton::Gethandlecount() << endl;
*/
pthread_t pthread_id[20];
void *val;
pthread_mutex_init(&mutex,NULL);
for(int i = 0;i < 20;i++)
{
pthread_create(&pthread_id[i],NULL,createl,NULL);
}
for(int i = 0;i < 20;i++)
{
pthread_join(pthread_id[i],&val);
}
pthread_mutex_destroy(&mutex);
return 0;
}