Pergunta

I have a class which has 3 static members. Each of static member is not thread-safe singleton. I need to provide a thread safe implementation for their use.Is it ok?Or I need to provide thread-safe wrapper for each of them? If I should - how can I do it using Lazy<T>?

Additional question : Measure() and Do() of SingeltonClass1/2/3 are not thread-safe is func1() thread-safe?

 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;
}

How should I re-implement MyLazySingleton if its constructor should get 2 arguments? string str and int i

I have asked a follow up question Thread-safe methods in the singleton class

Foi útil?

Solução

It's thread-safe as it is.

The default value for Lazy<T>'s LazyThreadSafetyMode is ExecutionAndPublication.

From the MSDN page on the new Lazy<T>(Func<T>) constructor:

An instance that is created with this constructor may be used concurrently from multiple threads.

The thread safety mode of a Lazy instance that is initialized with this constructor is LazyThreadSafetyMode.ExecutionAndPublication.

If you were to use another overload where you could pass a different LazyThreadSafetyMode value it wouldn't be thread safe. But using the constructor as you are now, it is thread safe.

EDIT: Regarding your additional edited question, if those methods on your SingletonClass1 type are not thread safe: then no, func1 is not thread safe either.

From the Lazy<T> MSDN Page:

Making the Lazy object thread safe does not protect the lazily initialized object. If multiple threads can access the lazily initialized object, you must make its properties and methods safe for multithreaded access.

You will need to make sure that those methods/interactions between those classes are thread safe. This might be as simple as wrapping the func1 body with a lock statement, but I can't say for certain depending on how your 3 instances of SingletonClass1 interact with each other or how calling code may access them.

Outras dicas

To ensure Thread-safety you have to set the LazyThreadSafetyMode parameter of the Lazy<T> constructor. There are 3 available values:

  • None: not thread-safe
  • PublicationOnly: many MyLazySingleton instance may be created, but only one will be published/returned by the Value property. Internally it uses Interlocked.CompareExchange
  • ExecutionAndPublication: The value is create only once

Here's an example:

new Lazy<Test>(() => new Test(), LazyThreadSafetyMode.ExecutionAndPublication)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top