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

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

这个是什么?

public StringBuilder Builder
{
    get { return _builder ?? (_builder = new StringBuilder()); }
}
有帮助吗?

解决方案

<强> BEGIN修改

根据您编辑的标题

,空 - 结合运营商自身似乎是线程安全的(见的菲尔哈克的分析)。它的出现,然而,这并不能保证对潜在多次调用StringBuilder的构造。

<强> END修改

您有螺纹的较大的问题,那就是建造属性本身表示可以在线程间共享状态。即使你做延迟初始化线程安全的,但也不能保证,食用生成器方法做在一个线程安全的方式。

// 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;
    }
}

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

  

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

如果您是在多线程消耗StringBuilder的,你可能是更好的服务,在你的类封装它。使构建私有和公开你需要为一个公共方法什么样的行为:

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

这样,你不是在写同步码所有的地方。

其他提示

这是不或多或少线程安全;你仍然可以有两个线程做在同一时间空校验,从而创建单独的对象,并没有看到其他的。

有两个版本NO

没有,既不是原子

给出的答案是正确的,两者都不是线程。事实上,他们大多是等价的,而??运营商只是编译器魔法使代码精简。你需要,如果你希望这成为线程使用一些同步机制。

我没有测试过这种方法我自己,但如果你想在无锁定方案的开销线程安全的,你是不是担心可能会创建并丢弃一个对象实例,你可以试试这个:

using System.Threading;

public StringBuilder Builder
{
    get 
    {
        if (_builder != null)
            Interlocked.CompareExchange( ref _builder, new StringBuilder(), null );
        return _builder; 
    }
}

要CompareExchange(呼叫)将在与_builder的StringBuilder的仅当_builder == NULL新实例执行的原子置换的值的。所有对互锁类的方法被gauranteed到NOT通过线程切换被抢占。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top