如何锁定调用者的功能并立即返回其他调用者?

时间:2019-01-18 14:42:27

标签: thread-safety locking

我有一个耗时的代码,它不是线程安全的,并且我想确保一次只有一个调用者可以使用它,而其他调用者应该得到一个错误或类似的东西,基本上立即返回。

这是我在C#中的方法:

public ErrorCodes SomeFunction()
{
  lock(_lock)
  {
    if(_beingUsed)
      return ErrorCodes.BeingUsed;

    _beingUsed = true;
  }

  // Time consuming code that is not thread safe.

  lock(_lock)
  {
    _beingUsed = false;
  }
}

但是我找不到与我的问题相似或不同的解决方案。够好吗?您有更好的建议吗?

1 个答案:

答案 0 :(得分:1)

我对您的方法进行了一些改进。

1)您需要添加try-finally块以设置保证的_beingUsed = false。否则,如果耗时的代码将引发异常,则任何调用者都无法运行此代码。

2)由于第一个锁下面的代码仅适用于一个调用者,因此我看不到第二个锁的需要。

以下是改进的代码:

public ErrorCodes SomeFunction()
{
    lock(_lock)
    {
        if(_beingUsed)
          return ErrorCodes.BeingUsed;

        _beingUsed = true;
    }

    // here can enter only one caller
    try
    {
        // Time consuming code that is not thread safe.
        return ErrorCodes.OK;
    }
    finally
    {
        _beingUsed = false;
    }
}

如果性能非常关键,则可以考虑使用无锁方法:

int _flag = 0;
public ErrorCodes SomeFunction()
{
    if (Interlocked.Exchange(ref _flag, 1) == 0)
    {
        // here can enter only one caller
        try
        {
            //process long operation
            return ErrorCodes.OK;
        }
        finally
        {
            Interlocked.Exchange(ref _flag, 0);
        }

    }
    else
    {
        //immediately return
        return ErrorCodes.BeingUsed;
    }
}

但是此代码看起来更复杂,并且需要了解无锁编程。