我有一个耗时的代码,它不是线程安全的,并且我想确保一次只有一个调用者可以使用它,而其他调用者应该得到一个错误或类似的东西,基本上立即返回。
这是我在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;
}
}
但是我找不到与我的问题相似或不同的解决方案。够好吗?您有更好的建议吗?
答案 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;
}
}
但是此代码看起来更复杂,并且需要了解无锁编程。