我有一个从多个线程访问的 C# 静态类。两个问题:
- 在声明时初始化字段时,我的私有(private)静态字段线程安全吗?
- 在静态构造函数中创建私有(private)静态字段时应该锁定吗?
不同线程静态类的使用:
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Task.Run(() =>
{
string name = MyStaticClass.GetValue(9555);
//...
});
}
}
}
静态类选项一:
public static class MyStaticClass
{
private static MyClass _myClass = new MyClass();
public static string GetValue(int key)
{
return _myClass.GetValue(key);
}
}
静态类的方案二:
public static class MyStaticClass
{
private static MyClass _myClass;
private static object _lockObj = new object();
static MyStaticClass()
{
InitMyClass();
}
private static void InitMyClass()
{
if (_myClass == null)
{
lock(_lockObj)
{
if (_myClass == null)
{
_myClass = new MyClass();
}
}
}
}
public static string GetValue(int key)
{
return _myClass.GetValue(key);
}
}
从静态类创建的实例类:
public class MyClass
{
private Dictionary<int, Guid> _valuesDict = new Dictionary<int, Guid>();
public MyClass()
{
for (int i = 0; i < 10000; i++)
{
_valuesDict.Add(i, Guid.NewGuid());
}
}
public string GetValue(int key)
{
if (_valuesDict.TryGetValue(key, out Guid value))
{
return value.ToString();
}
return string.Empty;
}
}
最佳答案
Should I lock when initializing private static fields from within static constructor?
让我们不要把 lede 埋在这里:
永远不要锁定静态构造函数。静态构造函数已被框架锁定,因此它们只在一个线程上运行一次。
这是一个更通用的好建议的特例:永远不要在静态构造函数中对线程做任何花哨的事情。事实上,静态构造函数被有效地锁定,并且任何访问您的类型的代码都可以争用该锁定,这意味着您可以很快陷入您没有预料到并且很难看到的死锁。我在这里举个例子:https://ericlippert.com/2013/01/31/the-no-lock-deadlock/
如果你想延迟初始化,使用 Lazy<T>
构造;它是由知道如何确保安全的专家编写的。
Are my private static fields thread safe when the field is initialized on declaration?
线程安全是当程序元素被多个线程调用时程序不变量的保存。你还没有说你的不变量是什么,所以不可能说你的程序是否“安全”。
如果您担心的不变量是观察到静态构造函数在执行第一个静态方法或创建第一个类型实例之前运行,C# 可以保证这一点。当然,如果您在静态构造函数中编写了疯狂的代码,那么疯狂的事情就会发生,所以再次尝试让您的静态构造函数非常简单。
关于c# - C# 静态类私有(private)字段线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53869832/