【问题标题】:Thread - safe singelton线程 - 安全单例
【发布时间】:2014-04-05 12:35:57
【问题描述】:

我有一个有 3 个静态成员的类。每个静态成员都不是线程安全的单例。 我需要为他们的使用提供一个线程安全的实现。可以吗?或者我需要为他们每个人提供线程安全的包装器?如果我应该 - 我该如何使用Lazy<T>

附加问题:SingeltonClass1/2/3 中的 Measure()Do() 不是线程安全的 func1() 是线程安全的吗?

 public class MyLazySingleton
 {
     // static holder for instance, need to use lambda to construct since constructor private
    private static readonly Lazy<MyLazySingleton> _instance
        = new Lazy<MyLazySingleton>(() => new MyLazySingleton());

     // private to prevent direct instantiation.
     private MyLazySingleton()
     {
             s_c1 = SingletonClass1.Instance();
             s_c2 = SingletonClass2.Instance();
             s_c3 = SingletonClass3.Instance();
    }

    // accessor for instance
    public static MyLazySingletonInstance
    {
        get
        {
            return _instance.Value;
        }
    }
    public void func1()
    {
        if (s_s1.Measure() || s_c2.Measure())
        {
           c_c3.Do();
        }
    }
       static SingletonClass1 s_c1 = null;
       static SingletonClass1 s_c2 = null;
       static SingletonClass1 s_c3 = null;
}

如果 MyLazySingleton 的构造函数应该获得 2 个参数,我应该如何重新实现它? string strint i

我已经问了一个后续问题Thread-safe methods in the singleton class

【问题讨论】:

  • 我编辑了我的答案以包含您的其他编辑/问题。如果您还有其他问题,可能需要一个新的有针对性的问题。
  • 我没有注意到您在底部编辑的 第三个 问题。您打算如何提供这些论点会影响答案。我建议您创建一个关于此的新问题特别。 (参数是编译时常量吗?你会更新你的MyLazySingletonInstance 来传递它们吗?用户会以某种方式指定它们吗?等等)

标签: c# multithreading lazy-evaluation


【解决方案1】:

它是线程安全的。

Lazy&lt;T&gt;LazyThreadSafetyMode 的默认值为ExecutionAndPublication

来自 new Lazy&lt;T&gt;(Func&lt;T&gt;) constructor 上的 MSDN 页面:

可以使用使用此构造函数创建的实例 从多个线程并发。

初始化的惰性实例的线程安全模式 这个构造函数是 LazyThreadSafetyMode.ExecutionAndPublication。

如果您使用another overload 可以传递一个不同 LazyThreadSafetyMode 值,那么它就不是线程安全的。但是像现在这样使用构造函数,它是线程安全的。

编辑:关于您的附加编辑问题,如果您的 SingletonClass1 类型上的这些方法是 not 线程安全的:那么 nofunc1 也不是线程安全的.

来自Lazy&lt;T&gt; MSDN Page

使惰性对象线程安全并不能保护惰性对象 初始化对象。如果多个线程可以懒惰地访问 初始化对象,您必须使其属性和方法安全 多线程访问。

您需要确保这些类之间的方法/交互是线程安全的。这可能就像用 lock 语句包装 func1 正文一样简单,但我不能确定这取决于您的 3 个 SingletonClass1 实例如何相互交互或如何调用代码可以访问它们。

【讨论】:

    【解决方案2】:

    为了确保线程安全,您必须设置Lazy&lt;T&gt; 构造函数的LazyThreadSafetyMode 参数。有 3 个可用值:

    • None:不是线程安全的
    • PublicationOnly:可以创建许多MyLazySingleton 实例,但Value 属性只会发布/返回一个实例。在内部它使用Interlocked.CompareExchange
    • ExecutionAndPublication: 价值只被创造一次

    这是一个例子:

    new Lazy<Test>(() => new Test(), LazyThreadSafetyMode.ExecutionAndPublication)
    

    【讨论】:

    • Yakov 不需要更改构造函数,也不需要指定线程安全。 Lazy 的默认值使它们成为线程安全的。为保证线程安全,Yakov不需要设置LazyThreadSafetyMode参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    相关资源
    最近更新 更多