我试图编写一个线程安全的方法(每个对象实例只能调用一次)。如果之前已调用过异常,则应抛出异常。

我提出了两种解决方案。他们都正确吗?如果没有,那他们怎么了?

  • lock 一起使用:
    public void Foo()
    {
        lock (fooLock)
        {
            if (fooCalled) throw new InvalidOperationException();
            fooCalled = true;
        }
        …
    }
    private object fooLock = new object();
    private bool fooCalled;
    
  • Interlocked.CompareExchange 一起使用:
    public void Foo()
    {
        if (Interlocked.CompareExchange(ref fooCalled, 1, 0) == 1)
            throw new InvalidOperationException();
        …
    }
    private int fooCalled;
    

    如果我没记错的话,此解决方案的优点是免锁(在我的情况下这似乎无关紧要),并且需要较少的私有(private)字段。

  • 如果有更好的方法,我也欢迎公开征询意见,最好选择哪种解决方案,并提出进一步的建议。

    最佳答案

    您的Interlocked.CompareExchange解决方案看起来最好,并且(如您所说)是无锁的。它也比其他解决方案复杂得多。锁非常重,而CompareExchange可以编译为单个CAS cpu指令。我说去那一个。

    关于c# - 如何: Write a thread-safe method that may only be called once?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9514411/

    10-11 05:31