c# - 在多线程(或 Web)c# 项目中使用静态属性的风险

标签 c# static thread-safety

我对 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/

相关文章:

c# - 通过看似不必要的字符串初始化来提升性能?

java - 通过配置更改保留对象的静态模式

cocoa - 如何在 Cocoa 中进行静态初始化

android - 如何将数据从一个 Activity 创建的后台线程发送到另一个已知处于 Activity 状态的 Activity ?

c# - 在没有 UAC/管理员权限的情况下托管 WCF 应用程序

c# - Automapper:更新属性值而不创建新对象

c# - 在 C# 中访问简单的 bool 标志时,是否需要锁定或标记为 volatile ?

python - Python 实例变量是线程安全的吗?

c# - Asp.Net MVC - 使用 Entity Framework + Npgsql.Entityframework 访问 Postgresql

java - 在静态方法中加载资源文件