C#中的``线程安全吗?

C#中的``线程安全吗?,c#,.net,thread-safety,C#,.net,Thread Safety,简单问题: “?”和“?。”和“?:”是线程安全的吗?我能相信他们吗?或者我应该使用其他线程安全解决方案? 例如,此代码: public static T Instance => _Instance ?? (_Instance = CreateInstance()); 线程安全吗??将读取一个在C#中保证是原子的引用(写入也是原子的)。因此,如果你的问题是,你是否可以用C#读写,答案是否定的 现在,这是否使公共静态T实例=>\u实例??(_Instance=CreateInstance(

简单问题: “
”和“
?。
”和“
?:
”是线程安全的吗?我能相信他们吗?或者我应该使用其他线程安全解决方案? 例如,此代码:

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

线程安全吗?

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

现在,这是否使
公共静态T实例=>\u实例??(_Instance=CreateInstance())线程安全?一般的答案是否定的,因为表达式有一个读和一个写,这绝对不是一个原子操作

可能出错的事情:

  • 竞态条件读取
    \u实例
    :一个线程可以在第二个线程初始化它之前将其读取为
    null
    。最后运行了两次
    CreateInstance()
    。这是个问题吗?如果是,则它不是线程安全的。如果不是,那么它可能是线程安全的,从性能角度来看不是最优的,但可能是安全的
  • 如何并发执行
    CreateInstance()
    ?这种情况安全吗?由于前面的竞争条件,也可能是一个线程在另一个线程退出之前进入
    CreateInstance
    。现在,您的问题不仅仅是
    CreateInstance
    运行两次,而是两次(或更多次)同时运行。安全吗

  • 因此,一般来说,这与
    CreateInstance()
    的安全程度一样安全。

    由于竞争条件,它不是线程安全的。(例如,线程A检查值,发现值为null,线程B检查值,发现值为null,线程B通过调用CreateInstance()初始化值,线程A通过调用CreateInstance()初始化值。)

    单例线程安全初始化的正确方法是使用类,例如:

    public T Instance => _instance.Value;
    
    static Lazy<T> _instance = new Lazy<T>(CreateInstance);
    
    public T Instance=>\u Instance.Value;
    静态惰性_实例=新惰性(CreateInstance);
    

    其中,
    CreateInstance()
    返回类型为
    T

    的实例。这里的问题不应该是如果
    ??
    是线程安全的,而应该是
    CreateInstance()
    是否是。如果假设
    CreateInstance()
    是线程安全的,您仍然需要询问
    表达式是否是线程安全的。@在这两者之间,让我们假设
    CreateInstance()
    是线程安全的。我想重点讨论
    @matthewatson是
    CreateInstance()
    是线程安全的。那
    ?。
    是一种完全不同的鱼。但不适用于你的例子。同意。它不是线程安全的,特别是如果您不想调用
    CreateInstance()
    两次,竞争条件是一个令人讨厌的条件。我应该在
    CreateInstance()中使用
    lock
    ?@mohammadmimormostafa,它不会有帮助,因为您需要同步对两个条件的访问:
    ??
    )和分配(
    CreateInstance())
    )。而是正确地使用
    Lazy
    it all synchronization。@Mohammadmormostafa如果可以从多个线程调用它,并且如果这样做可能导致问题,那么是的-但是我不可能在没有看到它的实现的情况下告诉您。请注意,如果调用它的唯一位置是从
    Lazy
    对象,那么您肯定不需要锁定它。