Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单例管理实现与线程安全_C#_Multithreading_Memory Leaks_Singleton - Fatal编程技术网

C# 单例管理实现与线程安全

C# 单例管理实现与线程安全,c#,multithreading,memory-leaks,singleton,C#,Multithreading,Memory Leaks,Singleton,我一直在研究实现单身的方法。我已经编写了一个小的管理对象,它允许使用更简单、更少代码的方法来编写单例类 我决不会在生产系统中使用这样的东西,因为有几个原因导致我提出了我的问题 使用以下代码-我假设此实现将/可能导致线程问题和内存泄漏?我说的对吗 namespace ConsoleApplication1 { public static class SingletonManager { private static readonly Dictionar

我一直在研究实现单身的方法。我已经编写了一个小的管理对象,它允许使用更简单、更少代码的方法来编写单例类

我决不会在生产系统中使用这样的东西,因为有几个原因导致我提出了我的问题

使用以下代码-我假设此实现将/可能导致线程问题和内存泄漏?我说的对吗

namespace ConsoleApplication1
{       
    public static class SingletonManager
    {
        private static readonly Dictionary<string, object> Objects;

        static SingletonManager()
        {
            Objects = new Dictionary<string, object>();
        }

        public static T InstanceOf<T>(object[] ctorArgs = null)
            where T : class
        {
            var name = typeof (T).FullName;
            if (Objects.ContainsKey(name))
                return Objects[name] as T;

            var ctor = typeof (T).GetConstructors(
                BindingFlags.Instance |
                BindingFlags.NonPublic)[0];

            var instance = ctor.Invoke(ctorArgs) as T;
            Objects[name] = instance;

            return instance as T;
        }

        public static void DisposeOf<T>()
            where T : Singleton<T>
        {
            Dispose(typeof (T).FullName);
        }

        public static void DisposeOf(Type type)
        {
            Dispose(type.FullName);
        }

        private static void Dispose(string name)
        {
            if (!Objects.ContainsKey(name)) return;

            var obj = Objects[name];
            if (obj is IDisposable)
                ((IDisposable) Objects[name]).Dispose();

            Objects.Remove(name);
        }
    }

    public class Singleton<T>
        where T : class
    {
        private static object ThreadLock = new object();

        public static T Instance(object[] ctorArgs = null)
        {
            lock (ThreadLock)
            {
                return SingletonManager.InstanceOf<T>(ctorArgs);
            }
        }
    }

    public class SomeSingletonClass : Singleton<SomeSingletonClass>
    {
        public int Number;

        private SomeSingletonClass(int i)
        {
            Number = i;
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var instance1= SomeSingletonClass.Instance(new object[] {1});

            var instance2 = SomeSingletonClass.Instance(new object[] { 2 });

            //Is false
            var updated = instance1.Number == 2;

            instance2.Number = 99;

            //Is true
            var equals = instance1.Number == instance2.Number;

            //Is true
            var refEquals = ReferenceEquals(instance1, instance2);

            Debugger.Break();
        }    
    }
}
命名空间控制台应用程序1
{       
公共静态类SingletonManager
{
私有静态只读字典对象;
静态SingletonManager()
{
Objects=新字典();
}
公共静态T InstanceOf(对象[]参数=null)
T:在哪里上课
{
var name=typeof(T).FullName;
if(Objects.ContainsKey(名称))
将对象[name]返回为T;
var ctor=typeof(T).GetConstructors(
BindingFlags.Instance|
BindingFlags.NonPublic)[0];
var instance=ctor.Invoke(ctorArgs)作为T;
对象[名称]=实例;
将实例返回为T;
}
公共静态无效处置()
T:单身汉
{
处置(类型为(T).全名);
}
公共静态无效处理(类型)
{
Dispose(type.FullName);
}
私有静态void Dispose(字符串名称)
{
如果(!Objects.ContainsKey(name))返回;
var obj=对象[名称];
如果(obj可识别)
((IDisposable)对象[名称]).Dispose();
对象。删除(名称);
}
}
公营单身人士
T:在哪里上课
{
私有静态对象ThreadLock=新对象();
公共静态T实例(对象[]或args=null)
{
锁紧(螺纹锁紧)
{
返回SingletonManager.InstanceOf(ctorArgs);
}
}
}
公共类SomeSingleton类:Singleton
{
公共整数;
私有单例类(int i)
{
数字=i;
}
}
内部课程计划
{
私有静态void Main(字符串[]args)
{
var instance1=SomeSingletonClass.Instance(新对象[]{1});
var instance2=SomeSingletonClass.Instance(新对象[]{2});
//是假的
var updated=instance1.Number==2;
实例2.Number=99;
//是真的
var=instance1.Number==instance2.Number;
//是真的
var refEquals=ReferenceEquals(instance1,instance2);
Debugger.Break();
}    
}
}
  • 经典的单身汉很少是个好主意。在大多数情况下,您最好只创建一个实例,并将其传递给需要它的代码,而不是强制要求只有一个实例。IoC容器将为您完成大部分工作

  • 经典单例的实现非常紧凑,无需进一步简化:

    public class MySingleton
    {
        private static Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton());    
        public static MySingleton Instance { get { return _instance.Value; } }
    
        private MySingleton()
        {
    
        }
    }
    
    公共类MySingleton
    {
    private static Lazy_instance=new Lazy(()=>new MySingleton());
    公共静态MySingleton实例{get{return}\u Instance.Value;}
    二等兵迈辛格尔顿()
    {
    }
    }
    
    最多可以保存其中两行

  • 是的,您的代码不是线程安全的。您需要将它的大部分放在
    lock
    语句中才能解决这个问题

  • 确定构造函数参数的使用者非常可疑。除非所有实例都相同,否则最终会得到不同的实例,具体取决于首先运行的消费者

    这违反了“单一真相来源”原则,是维护和调试的噩梦

  • 您的代码依赖于私有反射
  • 经典的单身汉很少是个好主意。在大多数情况下,您最好只创建一个实例,并将其传递给需要它的代码,而不是强制要求只有一个实例。IoC容器将为您完成大部分工作

  • 经典单例的实现非常紧凑,无需进一步简化:

    public class MySingleton
    {
        private static Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton());    
        public static MySingleton Instance { get { return _instance.Value; } }
    
        private MySingleton()
        {
    
        }
    }
    
    公共类MySingleton
    {
    private static Lazy_instance=new Lazy(()=>new MySingleton());
    公共静态MySingleton实例{get{return}\u Instance.Value;}
    二等兵迈辛格尔顿()
    {
    }
    }
    
    最多可以保存其中两行

  • 是的,您的代码不是线程安全的。您需要将它的大部分放在
    lock
    语句中才能解决这个问题

  • 确定构造函数参数的使用者非常可疑。除非所有实例都相同,否则最终会得到不同的实例,具体取决于首先运行的消费者

    这违反了“单一真相来源”原则,是维护和调试的噩梦

  • 您的代码依赖于私有反射
  • 经典的单身汉很少是个好主意。在大多数情况下,您最好只创建一个实例,并将其传递给需要它的代码,而不是强制要求只有一个实例。IoC容器将为您完成大部分工作

  • 经典单例的实现非常紧凑,无需进一步简化:

    public class MySingleton
    {
        private static Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton());    
        public static MySingleton Instance { get { return _instance.Value; } }
    
        private MySingleton()
        {
    
        }
    }
    
    公共类MySingleton
    {
    private static Lazy_instance=new Lazy(()=>new MySingleton());
    公共静态MySingleton实例{get{return}\u Instance.Value;}
    二等兵迈辛格尔顿()
    {
    }
    }
    
    最多可以保存其中两行

  • 是的,您的代码不是线程安全的。您需要将它的大部分放在
    lock
    语句中才能解决这个问题

  • 确定构造函数参数的使用者非常复杂