目前我有以下课程:
public class PluginManager
{
private static bool s_initialized;
private static object s_lock = new object();
public static void Initialize() {
if (!s_initialized) {
lock (s_lock) {
if (!s_initialized) {
// initialize
s_initialized = true;
}
}
}
}
}
重要的是,Initialize()只应在应用程序运行时执行一次。我以为我会把它重构成一个单例类,因为这样会更安全吗?:
public sealed class PluginService
{
static PluginService() { }
private static PluginService _instance = new PluginService();
public static PluginService Instance { get { return _instance; } }
private bool s_initialized;
public void Initialize() {
if (!s_initialized)
{
// initialize
s_initialized = true;
}
}
}
问题一,是否仍然需要锁定(我已将其删除),因为我们只会在同一个实例上工作?
最后,我想使用DI和结构图初始化我的服务,所以我重构如下:
public interface IPluginService {
void Initialize();
}
public class NewPluginService : IPluginService
{
private bool s_initialized;
public void Initialize() {
if (!s_initialized) {
// initialize
s_initialized = true;
}
}
}
在我的注册表中:
ForRequestedType<IPluginService>()
.TheDefaultIsConcreteType<NewPluginService>().AsSingletons();
这按预期工作(单例在以下代码中返回true):
var instance1 = ObjectFactory.GetInstance<IPluginService>();
var instance2 = ObjectFactory.GetInstance<IPluginService>();
bool singleton = (instance1 == instance2);
所以我的下一个问题是,结构图解决方案与单例类一样是线程安全的(第二个例子)。唯一的缺点是,这仍然允许直接实例化NewPluginService(如果不使用结构图)。
非常感谢, 本
答案 0 :(得分:3)
我会提出几点建议:
volatile
readonly
初始化不是线程安全的,无论你只有一个实例......所以它应该是同步的
public sealded class PluginService
{
static PluginService() { }
//make the instance readonly
private static readonly PluginService _instance = new PluginService();
public static PluginService Instance { get { return _instance; } }
// make the flag volatile
private static volatile bool s_initialized = false;
private static object s_lock = new object();
// you still need to synchronize when you're initializing
public void Initialize() {
lock(s_lock)
{
if (!s_initialized)
{
// initialize
s_initialized = true;
}
}
}
}
结构化地图上没有争用,因此其线程安全性似乎没有受到影响......
你拥有的单例类不是线程安全的。要记住的主要事情是单个实例不能确保单个线程只能访问它。如果有多个线程具有对该实例的引用,则该实例及其所持有的数据存在争用。如果存在争用,则应确保线程安全(至少同步)。