我对 C# 中静态属性的多线程访问风险有点困惑。
public class MyClass
{
public static MyClass Static
{
get
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
}
此示例类提供了一个静态属性,用于创建 MyClass 的新实例,
就像一个方法:
public class MyClass
{
public static MyClass Static()
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
显然,这个属性不是 MyClass 实例的“存储”框,但它的行为就像一个静态方法(如果我读了一篇不错的 msdn 文章,它是完全线程安全的)。
我的问题是:我使用这个概念会冒一些风险吗? 特别是在网络或多线程环境中?
使用它没有什么特别的用途,只是为了简单的阅读和清理代码:
MyClass.Static.SomeProperty = "Something";
比
更清晰MyClass.Static().SomeProperty = "Something";
所有帮助将不胜感激
谢谢
最佳答案
在这两个示例中,每次访问该属性时都会返回一个新的 MyClass
实例。当多个线程同时访问静态属性方法时,不会出现任何并发问题,因为它们实际上正在修改 MyClass<自己的实例的属性
并且不在他们之间共享它。
如果你有这样的东西:
public class MyClass
{
private static MyClass _myClass;
public static MyClass Static
{
get
{
return _myClass ?? (_myClass = new MyClass());
}
}
}
...那么当两个线程尝试写入/读取生成的 MyClass
实例的属性时,就会出现问题,因为它们在同一个 MyClass
上操作引用_myClass
。
即便如此,您发布的代码仍存在两个问题:
您需要将其更改为方法并重命名它,因为它实际上是在创建某些内容,而不是访问任何内容的静态版本。然后就可以对返回值进行操作了。像这样的事情:
public class MyClass
{
public static MyClass Create()
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
然后像这样使用它:
var myClass = MyClass.Create();
myClass.SomeProperty = "Stuff";
当前设置属性的方式意味着它们的值不会保留,因为下次访问 Static
属性时会创建一个新的 MyClass
。
如果当您设置 SomeProperty
时,您实际上希望更新静态实例,则需要锁定静态对象来解决多线程问题 - 如下所示:
public static class MyClass
{
private static readonly object locker = new object();
private static string someProperty;
public void SetSomeProperty(string val)
{
lock (locker)
{
someProperty = val;
}
}
public void GetSomeProperty()
{
lock (locker)
{
return someProperty;
}
}
}
关于c# - 在多线程(或 Web)c# 项目中使用静态属性的风险,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16840644/