【问题标题】:Static object thread safety静态对象线程安全
【发布时间】:2014-05-03 13:31:27
【问题描述】:

我有一个预加载的静态 xmldocument 对象,其中包含错误代码及其描述, 如果我正在使用多线程应用程序并尝试获取特定错误代码的错误代码描述,我是否需要锁定该方法。

这里是我的简单代码(请忽略GetErrorCodeDescription方法的实现,只考虑使用了_oXmlDoc),

预加载的静态 xmldocument _oXmlDoc

稍后我调用 GetErrorCodeDescription 方法来获取这样的错误代码描述,

Public string GetErrorCodeDescription(string errorCode)
{
string errorDEscption="";

    XmlNodeList elemList = **_oXmlDoc**.GetElementsByTagName(errorCode);

    for (int i=0; i < elemList.Count; i++)
    {   
      errorDEscption=elemList[i].InnerXml);
    }  

return errorDEscption;

}

【问题讨论】:

    标签: c# multithreading static thread-safety static-members


    【解决方案1】:

    最好只对 XML 进行一次解析,然后将所有错误代码和相应的描述放入字典中。如果你为此使用ConcurrentDictionary,你应该是安全的。

    【讨论】:

    • ConcurrentDictionary 太慢了。普通字典 线程安全的,仅用于阅读。
    【解决方案2】:

    来自the XmlDocument docs

    线程安全

    此类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。 不保证任何实例成员都是线程安全的。

    所以,不,不保证使用您的静态实例在没有锁定的情况下是线程安全的。

    【讨论】:

    • @user3597242 文档中没有规定读取操作的线程安全。查询对象可能 - 例如 - 使用非线程安全集合构建缓存。
    • 正式正确,但这是 MSDN 上的模板文本。如果只读不安全,我会感到惊讶,但唯一确定的方法是检查来源或找到更权威的声明。
    • @HenkHolterman 我认为你很难找到比文档提供更多线程安全保证的人。据我了解.NET内存模型,如果在构造对象和读取对象之间没有fence,那么在另一个CPU上第一次读取时,可能会没有完全写入内存。这里不一定是问题,但很难排除,而且当它发生时很难发现。
    • 请注意,我在 windows 服务启动事件中构建/加载 xmldocument,之后加载的静态实例将在 timer_tick 线程中如上述代码中所述使用。因为它已创建单线程环境并且在多线程环境中阅读,我觉得它是线程安全的。如果我错了,请纠正我。
    • @user3597242 可能是,但不能保证是线程安全的。即使是现在,它也可能在未来的 .NET 版本中发生变化。文档没有说任何一种方式,他们只是说“不要假设它是”。
    猜你喜欢
    • 2014-09-16
    • 2012-09-22
    • 2015-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    相关资源
    最近更新 更多