简单问题:
“??
”和“?.
”以及“? :
”线程安全吗?我能相信他们吗?或者我应该使用其他线程安全解决方案?
例如这段代码:
public static T Instance => _Instance ?? (_Instance = CreateInstance());
是线程安全的吗?
答案 0 :(得分:2)
??
将读取一个在C#中保证为原子的引用(写入也是如此)。因此,如果你的问题是,你可以用C#撕掉参考读取或写入,答案是否定的。
现在,这会使public static T Instance => _Instance ?? (_Instance = CreateInstance());
线程安全吗?一般的答案是否定的,因为表达式有一个读取和一个写入,这绝对不是原子操作。
可能出错的事情:
_Instance
:一个线程可以在第二个线程初始化它之前将其读作null
。您最终运行CreateInstance()
两次。那是问题吗?如果是,那么它不是线程安全的。如果不是,那么它可以是线程安全的,从性能的角度来看不是最优的,但可能是安全的。CreateInstance()
的并发执行怎么样?这种情况安全吗?由于之前的竞争条件,一个线程也可能在另一个线程退出之前进入CreateInstance
。现在你的问题不是CreateInstance
运行两次,而是两个(或更多)并发运行。这样安全吗?一般而言,这与安全CreateInstance()
的安全性一样安全。
答案 1 :(得分:2)
由于竞争条件,它不是线程安全的。 (例如,线程A检查值,发现它为空,线程B检查值,发现它为空,线程B通过调用CreateInstance()初始化值,线程A通过调用CreateInstance()来初始化值。)
单例的线程安全初始化的正确方法是使用Lazy<T>
类,例如:
v="8.0.3.0"
echo "${v%*.*.*}-${v#*.*.}"
其中public T Instance => _instance.Value;
static Lazy<T> _instance = new Lazy<T>(CreateInstance);
返回CreateInstance()
类型的实例。