Rao*_*bin 15 c# singleton multithreading
我一直在使用这种模式来初始化我的类中的静态数据.它看起来对我来说是安全的,但我知道细微的线程问题是多么微妙.这是代码:
public class MyClass // bad code, do not use
{
static string _myResource = "";
static volatile bool _init = false;
public MyClass()
{
if (_init == true) return;
lock (_myResource)
{
if (_init == true) return;
Thread.Sleep(3000); // some operation that takes a long time
_myResource = "Hello World";
_init = true;
}
}
public string MyResource { get { return _myResource; } }
}
Run Code Online (Sandbox Code Playgroud)
这里有洞吗?也许有一种更简单的方法可以做到这一点.
更新:共识似乎是静态构造函数是要走的路.我使用静态构造函数提出了以下版本.
public class MyClass
{
static MyClass() // a static constructor
{
Thread.Sleep(3000); // some operation that takes a long time
_myResource = "Hello World";
}
static string _myResource = null;
public MyClass() { LocalString = "Act locally"; } // an instance constructor
// use but don't modify
public bool MyResourceReady { get { return _myResource != null; } }
public string LocalString { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我希望这更好.
小智 12
您可以使用静态构造函数初始化静态变量,C#guarantee仅在每个AppDomain中调用一次.不确定你是否考虑过它们.
所以你可以读到这个:http://msdn.microsoft.com/en-us/library/aa645612(VS.71).aspx(静态构造函数)
执行lock()
上_myResource
并改变它里面lock()
的语句似乎是一个坏主意.考虑以下工作流程
MyClass()
._init = true;
分配后,执行在行之前停止_myResource
.MyClass()
.由于_init
仍然false
和refrence _myResource
更改,它成功进入lock()
语句块._init
仍然是false
,所以线程2重新分配_myResource
.解决方法:创建静态object
并锁定此对象而不是初始化资源:
private static readonly object _resourceLock = new object();
/*...*/
lock(_resourceLock)
{
/*...*/
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8723 次 |
最近记录: |