Ars*_*yan 8 .net c# thread-safety null-coalescing-operator
每个人都知道这不是线程安全的:
public StringBuilder Builder
{
get
{
if (_builder != null)
_builder = new StringBuilder();
return _builder;
}
}
Run Code Online (Sandbox Code Playgroud)
那这个呢?
public StringBuilder Builder
{
get { return _builder ?? (_builder = new StringBuilder()); }
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*ows 10
开始编辑
根据您编辑的标题,null-coalescing运算符本身似乎是线程安全的(参见Phil Haack的分析).但是,它似乎并不能保证不会对StringBuilder构造函数进行多次调用.
结束编辑
线程有一个更大的问题,那就是Builder属性本身代表可以跨线程共享的状态.即使你使延迟初始化线程安全,也不能保证使用Builder的方法以线程安全的方式进行.
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
上面将防止_builder的延迟初始化中的线程问题,但除非您同步调用StringBuilder的实例方法,否则在使用Builder属性的任何方法中都不能保证线程安全.这是因为StringBuilder中的实例方法并非设计为线程安全的.请参阅MSDN StringBuilder页面中的以下文本.
此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的.任何实例成员都不保证是线程安全的.
如果你在多个线程中使用StringBuilder,那么你可能会更好地将它封装在你的类中.使构建器变为私有并公开您需要的行为作为公共方法:
public void AppendString(string toAppend)
{
lock (Builder)
{
Builder.Append(toAppend);
}
}
Run Code Online (Sandbox Code Playgroud)
这样你就不会在整个地方编写同步代码.