多线程安全的Singleton单件方式在C++,java与C#下的实现

多线程安全的Singleton单件模式在C++,java与C#下的实现

        单件模式就是全局只能被创建一个对象,在没有多线程的情况粗糙的代码还可以

 

 

class Singleton
{
private:
        static Singleton* Instance;
protected:
        Singleton(){};
public:
       static Singleton* GetInstance()
       {
                                        
              if(Instance==NULL)
                {
                   Instance=new Singleton();
                }
              return Instance;
       }

};


        在多线程情况就会出问题,就是在if(Instance==NULL)之后有可能一个线程的时间用光,现一个线程也进行判断就业可以成功创建对象。

        多线程安全的Singleton在C++下可以用锁,在加锁内外进行两次判断

#include <iostream>
<span style="color:#ff0000;">#include<pthread.h></span>
using namespace std;
<span style="font-size:12px;">class Singleton
{
private:
        <span style="color:#000099;">static Singleton* Instance;</span>
        <span style="color:#ff0000;">static pthread_mutex_t mutex;</span>
protected:
        Singleton(){};
public:
       static Singleton* GetInstance()
       {
                if(Instance==NULL)//锁内外两次判断
                {
                        <span style="color:#ff0000;">pthread_mutex_lock(&mutex);
</span>                        if(Instance==NULL)
                        {
                                Instance=new Singleton();
                        }
                        <span style="color:#ff0000;">pthread_mutex_unlock(&mutex);</span>
                }
                return Instance;
       }

};
</span>

 

        多线程安全的Singleton在java下可以用synchronized同步getInstance()方法,这样创建时的getInstance()就不会同时在两处执行。

<span style="font-size:12px;color:#000000;">import java.awt.image.SinglePixelPackedSampleModel;

import javax.swing.SingleSelectionModel;

public class Singleton
{
	private static Singleton uniqueInstance;
	private Singleton(){};
	public static <span style="color:#ff0000;">synchronized</span> Singleton getInstance()//把getInstance方法同步,就避免多线程不安全了
	{
		if(uniqueInstance==null)
		{
			uniqueInstance=new Singleton();
		}
		return uniqueInstance;
	}
}
</span>


        多线程安全的Singleton在C#下还是用锁

<span style="font-size:12px;">public class Singleton
    {
        private static Singleton instance = null;
        private static object lockHelper = new object();
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (lockHelper)
                    {
                        if (instance == null)
                        {
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
        }
    }


</span>

 

         C#有个关键字叫volatile,他的作用,简单来说,编译器编译我们的代码时候,会对代码作一些优化,进而对代码进行了微调,使用volatile关键字就可以避免这个微调。继而严格意义上保证不会产生多线程。

public class Singleton
    {
        private static <span style="color:#ff0000;">volatile</span> Singleton instance = null;
        private static object lockHelper = new object();
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (lockHelper)
                    {
                        if (instance == null)
                        {
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
        }
    }



        也可以使用.net特有的支持多线程的单件模式

<span style="font-size:14px;">public sealed class Singleton
    {
        public static readonly Singleton Instance;
        static Singleton()
        {
            Instance = new Singleton();
        }
        private Singleton() { }
    }
</span>


        sealed 修饰符表示该类是密封类,不能被继承。你可以按需修改。上述代码在编译时,会使用一个名为beforefieldinit元数据标志。此标志使得运行库能够在任何时候执行类型构造函数方法,只要该方法在第一次访问该类型的静态字段之前执行即可。换句话说,beforefieldinit 为运行库提供了一个执行主动优化的许可。如果没有beforefieldinit,运行库就必须在某个精确时间运行类型构造函数,即,恰好在第一次访问该类型的静态或实例字段和方法之前。静态构造器自身就可以保证,多线程情况下,系统就可以保证只有一个执行。