在C#中```线程是否安全?

时间:2017-01-30 11:48:07

标签: c# .net thread-safety

简单问题: “??”和“?.”以及“? :”线程安全吗?我能相信他们吗?或者我应该使用其他线程安全解决方案? 例如这段代码:

public static T Instance => _Instance ?? (_Instance = CreateInstance());

是线程安全的吗?

2 个答案:

答案 0 :(得分:2)

??将读取一个在C#中保证为原子的引用(写入也是如此)。因此,如果你的问题是,你可以用C#撕掉参考读取或写入,答案是否定的。

现在,这会使public static T Instance => _Instance ?? (_Instance = CreateInstance());线程安全吗?一般的答案是否定的,因为表达式有一个读取和一个写入,这绝对不是原子操作。

可能出错的事情:

  1. 竞争条件读取_Instance:一个线程可以在第二个线程初始化它之前将其读作null。您最终运行CreateInstance()两次。那是问题吗?如果是,那么它不是线程安全的。如果不是,那么它可以是线程安全的,从性能的角度来看不是最优的,但可能是安全的。
  2. CreateInstance()的并发执行怎么样?这种情况安全吗?由于之前的竞争条件,一个线程也可能在另一个线程退出之前进入CreateInstance。现在你的问题不是CreateInstance运行两次,而是两个(或更多)并发运行。这样安全吗?
  3. 一般而言,这与安全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()类型的实例。