Ada*_*dam 7 c# atomic null-coalescing-operator
我今天在代码库中遇到了一些单例代码,我不确定以下是否是线程安全的:
public static IContentStructure Sentence{
get {
return _sentence ?? (_sentence = new Sentence());
}
}
Run Code Online (Sandbox Code Playgroud)
该陈述相当于:
if (_sentence != null) {
return _sentence;
}
else {
return (_sentence = new Sentence());
}
Run Code Online (Sandbox Code Playgroud)
我相信 ??只是一个编译器技巧,结果代码仍然不是原子的.换句话说,在将_sentence设置为新句子并返回之前,两个或多个线程可以找到_sentence为null.
为了保证原子性,我们必须锁定那段代码:
public static IContentStructure Sentence{
get {
lock (_sentence) { return _sentence ?? (_sentence = new Sentence()); }
}
}
Run Code Online (Sandbox Code Playgroud)
那一切都正确吗?
Eri*_*ert 16
我今天在代码库中遇到了一些单例代码
你的代码库中是否有这种混淆代码?这段代码做了同样的事情:
if (_s == null)
_s = new S();
return _s;
Run Code Online (Sandbox Code Playgroud)
并且大约容易阅读一千倍.
我相信 ??只是一个编译器技巧,结果代码仍然不是原子的
你是对的.C#提供以下原子性保证:
以下数据类型的读取和写入是原子的:bool,char,byte,sbyte,short,ushort,uint,int,float和reference类型.此外,在先前列表中具有基础类型的枚举类型的读取和写入也是原子的.其他类型的读写,包括long,ulong,double和decimal,以及用户定义的类型,不保证是原子的.除了为此目的而设计的库函数之外,不保证原子读 - 修改 - 写,例如在递增或递减的情况下.
空合并运算符不在该保证列表上.
为了保证原子性,我们必须锁定那段代码:
lock (_sentence) { return _sentence ?? (_sentence = new Sentence()); } } }
Run Code Online (Sandbox Code Playgroud)
天哪没有.那立刻就崩溃了!
正确的做法是:
Lazy<T>课程.