如何避免在不阻塞的情况下并发调用方法?
Howto avoid concurrently calling a method without blocking?
我想要 运行 一个可能 运行 几秒钟的清理任务。多个线程可以调用此任务,但我只想 运行 此任务一次。所有其他调用都应该跳过。
以下是我目前的实现,但我无法想象在 .net 框架中没有更好的解决方案,从而减少代码行数。
object taskLock;
bool isRunning;
void Task()
{
if (isRunning) return;
try
{
lock (taskLock)
{
if (isRunning) return;
isRunning = true;
}
// Perform the magic
}
finally
{
isRunning = false;
}
}
是的,有更好的解决方案。可以使用Interlocked.CompareExchange,代码变得更简单无锁:
class Worker
{
private volatile int isRunning = 0;
public void DoWork()
{
if (isRunning == 0 && Interlocked.CompareExchange(ref isRunning, 1, 0) == 0)
{
try
{
DoTheMagic();
}
finally
{
isRunning = 0;
}
}
}
private void DoTheMagic()
{
// do something interesting
}
}
在这种情况下 Interlocked.CompareExchange
作为原子操作(伪代码)执行以下操作:
wasRunning = isRunning;
if isRunning = 0 then
isRunning = 1
end if
return wasRunning
来自 MSDN 文档:
public static int CompareExchange(
ref int location1,
int value,
int comparand
)
If comparand and the value in location1 are equal, then value is
stored in location1. Otherwise, no operation is performed. The compare
and exchange operations are performed as an atomic operation. The
return value of CompareExchange is the original value in location1,
whether or not the exchange takes place
我想要 运行 一个可能 运行 几秒钟的清理任务。多个线程可以调用此任务,但我只想 运行 此任务一次。所有其他调用都应该跳过。
以下是我目前的实现,但我无法想象在 .net 框架中没有更好的解决方案,从而减少代码行数。
object taskLock;
bool isRunning;
void Task()
{
if (isRunning) return;
try
{
lock (taskLock)
{
if (isRunning) return;
isRunning = true;
}
// Perform the magic
}
finally
{
isRunning = false;
}
}
是的,有更好的解决方案。可以使用Interlocked.CompareExchange,代码变得更简单无锁:
class Worker
{
private volatile int isRunning = 0;
public void DoWork()
{
if (isRunning == 0 && Interlocked.CompareExchange(ref isRunning, 1, 0) == 0)
{
try
{
DoTheMagic();
}
finally
{
isRunning = 0;
}
}
}
private void DoTheMagic()
{
// do something interesting
}
}
在这种情况下 Interlocked.CompareExchange
作为原子操作(伪代码)执行以下操作:
wasRunning = isRunning;
if isRunning = 0 then
isRunning = 1
end if
return wasRunning
来自 MSDN 文档:
public static int CompareExchange(
ref int location1,
int value,
int comparand
)
If comparand and the value in location1 are equal, then value is stored in location1. Otherwise, no operation is performed. The compare and exchange operations are performed as an atomic operation. The return value of CompareExchange is the original value in location1, whether or not the exchange takes place