是C#“?”操作线程安全的?
-
09-09-2019 - |
题
大家都知道,这是不是线程安全的:
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通过线程切换被抢占。