uri*_*ini 242 c# singleton multithreading
换句话说,这个Singleton实现线程是否安全:
public class Singleton
{
private static Singleton instance;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
}
public static Singleton Instance
{
get { return instance; }
}
}
Run Code Online (Sandbox Code Playgroud)
Zoo*_*oba 185
在创建类的任何实例或访问任何静态成员之前,保证每个应用程序域只运行一次静态构造函数.http://msdn.microsoft.com/en-us/library/aa645612.aspx
显示的实现对于初始构造是线程安全的,也就是说,构造Singleton对象不需要锁定或空测试.但是,这并不意味着将同步实例的任何使用.有多种方法可以做到这一点; 我在下面展示了一个.
public class Singleton
{
private static Singleton instance;
// Added a static mutex for synchronising use of instance.
private static System.Threading.Mutex mutex;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
mutex = new System.Threading.Mutex();
}
public static Singleton Acquire()
{
mutex.WaitOne();
return instance;
}
// Each call to Acquire() requires a call to Release()
public static void Release()
{
mutex.ReleaseMutex();
}
}
Run Code Online (Sandbox Code Playgroud)
Bri*_*lph 85
虽然所有这些答案都给出了相同的一般答案,但有一点需要注意.
请记住,泛型类的所有潜在派生都是作为单独的类型编译的.因此在为泛型类型实现静态构造函数时要小心.
class MyObject<T>
{
static MyObject()
{
//this code will get executed for each T.
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
这是演示:
static void Main(string[] args)
{
var obj = new Foo<object>();
var obj2 = new Foo<string>();
}
public class Foo<T>
{
static Foo()
{
System.Diagnostics.Debug.WriteLine(String.Format("Hit {0}", typeof(T).ToString()));
}
}
Run Code Online (Sandbox Code Playgroud)
在控制台中:
Hit System.Object
Hit System.String
Run Code Online (Sandbox Code Playgroud)
Der*_*ark 28
使用静态构造函数实际上是线程安全的.静态构造函数保证只执行一次.
来自C#语言规范http://msdn.microsoft.com/en-us/library/aa645612(VS.71).aspx:
类的静态构造函数在给定的应用程序域中最多执行一次.静态构造函数的执行由应用程序域中发生的以下第一个事件触发:
- 创建了一个类的实例.
- 引用该类的任何静态成员.
所以,是的,您可以相信您的单例将被正确实例化.
Zooba提出了一个很好的观点(在我之前15秒!)静态构造函数不保证对单例的线程安全共享访问.这将需要以另一种方式处理.
小智 8
这是c#singleton上面MSDN页面中的Cliffnotes版本:
使用以下模式,总是,你不能出错:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton(){}
public static Singleton Instance
{
get
{
return instance;
}
}
}
Run Code Online (Sandbox Code Playgroud)
除了明显的单例功能之外,它还免费提供这两件事(就c ++中的单例而言):
保证静态构造函数在每个App Domain中仅触发一次,因此您的方法应该可以。但是,它在功能上与更简洁的嵌入式版本没有什么不同:
private static readonly Singleton instance = new Singleton();
Run Code Online (Sandbox Code Playgroud)
延迟初始化事物时,线程安全性更成问题。
静态构造函数将在允许任何线程访问该类之前完成运行。
private class InitializerTest
{
static private int _x;
static public string Status()
{
return "_x = " + _x;
}
static InitializerTest()
{
System.Diagnostics.Debug.WriteLine("InitializerTest() starting.");
_x = 1;
Thread.Sleep(3000);
_x = 2;
System.Diagnostics.Debug.WriteLine("InitializerTest() finished.");
}
}
private void ClassInitializerInThread()
{
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.GetHashCode() + ": ClassInitializerInThread() starting.");
string status = InitializerTest.Status();
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.GetHashCode() + ": ClassInitializerInThread() status = " + status);
}
private void classInitializerButton_Click(object sender, EventArgs e)
{
new Thread(ClassInitializerInThread).Start();
new Thread(ClassInitializerInThread).Start();
new Thread(ClassInitializerInThread).Start();
}
Run Code Online (Sandbox Code Playgroud)
上面的代码产生了下面的结果。
10: ClassInitializerInThread() starting.
11: ClassInitializerInThread() starting.
12: ClassInitializerInThread() starting.
InitializerTest() starting.
InitializerTest() finished.
11: ClassInitializerInThread() status = _x = 2
The thread 0x2650 has exited with code 0 (0x0).
10: ClassInitializerInThread() status = _x = 2
The thread 0x1f50 has exited with code 0 (0x0).
12: ClassInitializerInThread() status = _x = 2
The thread 0x73c has exited with code 0 (0x0).
Run Code Online (Sandbox Code Playgroud)
即使静态构造函数需要很长时间才能运行,其他线程也会停止并等待。所有线程都读取静态构造函数底部设置的 _x 值。
归档时间: |
|
查看次数: |
59357 次 |
最近记录: |