【问题标题】:What is mean by thread safe线程安全是什么意思
【发布时间】:2015-06-02 12:07:06
【问题描述】:

我一直在经历单例模式,但我不明白下面的代码是如何线程安全的:

public class ThreadSafeSingleton
{
    private ThreadSafeSingleton()
    {
    }

    public static ThreadSafeSingleton Instance
    {
        get { return Nested.instance; }
    }

    private class Nested
    {
        static Nested()
        {
        }

        internal static readonly ThreadSafeSingleton instance = new ThreadSafeSingleton();
    }
}

为什么这是线程安全的?

【问题讨论】:

  • Jon Skeet 在这里讨论这个csharpindepth.com/articles/general/singleton.aspx
  • @kenny 谢谢这正是我们需要的......
  • 请注意,这是单例的“过于臃肿”的版本。 private readonly static ThreadSafeSingleton instance = new ThreadSafeSingleton(); 就足够了

标签: c# design-patterns


【解决方案1】:

CLR 只执行一次静态构造函数。指定这样做。因此,instance 仅被初始化一次。这使得这个线程安全。

如何实现线程安全是一个实现细节。

【讨论】:

    【解决方案2】:

    请在下面找到线程安全单例实现的实现。

    另外,你可以使用这个question 有用。它提供了不会影响性能的双重锁定线程安全性。

    查找静态here的参考

    找到参考here

    以下代码不是线程安全的。两个不同的线程都可以评估测试 if (instance==null) 并发现它为真,然后都创建实例,这违反了单例模式。请注意,实际上在计算表达式之前可能已经创建了实例,但是内存模型不保证实例的新值将被其他线程看到,除非已经通过了合适的内存屏障。

    不是线程安全的单例

    // Bad code! Do not use!
    public sealed class Singleton
    {
        private static Singleton instance=null;
    
        private Singleton()
        {
        }
    
        public static Singleton Instance
        {
            get
            {
                if (instance==null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    } 
    

    线程安全实现:

    公共密封类 Singleton { 私有静态单例实例 = null; private static readonly object padlock = new object();

    Singleton()
    {
    }
    
    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
    

    }

    这个实现是线程安全的。线程在共享对象上取出一个锁,然后在创建实例之前检查实例是否已经创建。这解决了内存屏障问题(因为锁定确保所有读取在获得锁之后逻辑发生,而解锁确保所有写入在锁释放之前逻辑发生)并确保只有一个线程会创建一个实例(因为只有一个线程一次可以在该部分代码中 - 当第二个线程进入它时,第一个线程将创建实例,因此表达式将评估为假)。不幸的是,每次请求实例时都会获取锁,因此性能会受到影响。

    【讨论】:

      猜你喜欢
      • 2014-05-19
      • 2015-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-29
      • 1970-01-01
      • 2011-09-26
      • 1970-01-01
      相关资源
      最近更新 更多