1

我对 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";

所有帮助将不胜感激

谢谢

4

3 回答 3

2

似乎您正在创建一个静态工厂方法,该方法将为您提供一个完全实例化的对象。

线程在这里不是问题,因为每次调用此方法或属性时,您都在创建一个新对象。如果 2 个线程同时调用相同的方法,它们将各自继续处理它们正在处理的对象

话虽如此 - 也许你应该重新检查你是如何使用这个类的 - 因为如果你在你的代码中调用它

MyClass.Static.SomeProperty = "Something";

您基本上是在实例化对象后将其丢弃,您需要将其分配给变量并存储它。- 下次调用该函数时,您将收到一个新对象。

于 2013-05-30T16:06:25.963 回答
2

在您的两个示例中,您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";

您当前设置属性的方式意味着它们的值不会持久化,因为MyClass下次Static访问该属性时会创建一个新值。

如果您在设置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;
        }
    }
}
于 2013-05-30T16:13:56.307 回答
0

也许我无法正确解释,我的问题是关于静态属性的多线程访问。

如果返回的对象绑定到当前线程,我可以确认它们是线程安全的。

这是我实现的示例:

public interface IObjectFactory
{
    T CreateOrReuse<T>() where T : class, new();
    T CreateOrReuse<T>(string key) where T : class, new();
    T CreateOrReuse<T>(string key, params object[] args) where T : class;
}

public class ThreadObjectFactory : IObjectFactory
{
    // implementation to create and store into the Thread Data
}

public class HttpSessionObjectFactory : IObjectFactory
{
    // implementation to create and store into the current session
}

现在单例:

public class MyClass
{
    public int PageLoadCounter = 0;

    public static MyClass Static
    {
        get
        {
            IObjectFactory factory = new HttpSessionObjectFactory();
            return factory.CreateOrReuse<MyClass>();
        }
    }
}

这是最终用途:

public class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        MyClass.Static.PageLoadCounter++;
    }
}

感谢您的回复,即使问题不是很清楚

于 2013-08-21T14:59:25.593 回答