问题
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
回答1:
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.
回答2:
To ensure Thread-safety you have to set the LazyThreadSafetyMode
parameter of the Lazy<T>
constructor. There are 3 available values:
None
: not thread-safePublicationOnly
: manyMyLazySingleton
instance may be created, but only one will be published/returned by theValue
property. Internally it usesInterlocked.CompareExchange
ExecutionAndPublication
: The value is create only once
Here's an example:
new Lazy<Test>(() => new Test(), LazyThreadSafetyMode.ExecutionAndPublication)
来源:https://stackoverflow.com/questions/22880978/thread-safe-singelton