是C#'?“运营商线程安全的? [英] Is the C# '??' operator thread safe?

查看:194
本文介绍了是C#'?“运营商线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家都知道,这是不是线程安全的:

 公开的StringBuilder生成器
{
    得到
    {
        如果(_builder!= NULL)
            _builder =新的StringBuilder();
        返回_builder;
    }
}
 

这个怎么样?

 公开的StringBuilder生成器
{
    {返回_builder? (_builder =新的StringBuilder()); }
}
 

解决方案

BEGIN修改

根据您编辑的标题

,以空合并运算符本身似乎是线程安全的(见菲尔哈克的分析)。它的出现,但是,它并没有对潜在的多次调用StringBuilder的构造保证。

END修改

您有一个更大的问题与线程,那就是建造财产本身重新presents状态,可以在线程间共享。即使你做了延迟初始化线程安全的,但也不能保证,食用Builder的方法做在一个线程安全的方式。

  //低于code这样getter线程安全
私有对象builderConstructionSynch =新的对象();
公众的StringBuilder生成器
{
    得到
    {
        锁定(builderConstructionSynch)
        {
            如果(_builder == NULL)_builder =新的StringBuilder();
        }
        返回_builder;
    }
}
 

以上的意志prevent在_builder的延迟初始化线程问题,但除非你同步调用的StringBuilder的实例方法,你不能保证线程安全的消耗建造财产的任何方法。这是因为在StringBuilder的实例方法的目的不是线程安全的。请参见下面的文本从 MSDN StringBuilder的页面

  

任何公共static(在Visual共享   这种类型的基础)成员都是线程   安全。任何实例成员都没有   保证线程安全的。

如果你消费的StringBuilder在多线程,你可能会更好曾在你的类封装了。使生成私人和公开哪些行为需要作为一个公共方法:

 公共无效AppendString(字符串toAppend)
{
    锁定(生成器)
    {
        Builder.Append(toAppend);
    }
}
 

这样你不写同步code所有的地方。

Everyone knows that this is not thread safe:

public StringBuilder Builder
{
    get 
    {
        if (_builder != null)
            _builder = new StringBuilder();
        return _builder; 
    }
}

What about this?

public StringBuilder Builder
{
    get { return _builder ?? (_builder = new StringBuilder()); }
}

解决方案

BEGIN EDIT

Based on your edited title, the null-coalescing operator itself seems to be thread-safe (see Phil Haack's analysis). It appears, however, that it doesn't guarantee against the potential multiple calls to the StringBuilder constructor.

END EDIT

You have a larger problem with threading, and that is that the Builder property itself represents state that can be shared across threads. Even if you make the lazy initialization thread safe, there's no guarantee that methods consuming Builder are doing it in a thread safe manner.

// below code makes the getter thread safe
private object builderConstructionSynch = new object();
public StringBuilder Builder
{
    get
    {
        lock (builderConstructionSynch)
        {
            if (_builder == null) _builder = new StringBuilder();
        }
        return _builder;
    }
}

The above will prevent the threading problem in the lazy initialization of _builder, but unless you synchronize your calls to instance methods of StringBuilder, you're not guaranteed thread safety in any methods that consume the Builder property. This is because instance methods in StringBuilder weren't designed to be thread safe. See the below text from the MSDN StringBuilder page.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

If you're consuming StringBuilder in multiple threads, you're probably better served encapsulating it in your class. Make Builder private and expose what behavior you need as a public method:

public void AppendString(string toAppend)
{
    lock (Builder)
    {
        Builder.Append(toAppend);
    }
}

This way you're not writing synchronization code all over the place.

这篇关于是C#'?“运营商线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆