假设我有一个被多个线程调用的方法
public class MultiThreadClass
{
public void Gogogo()
{
// method implementation
}
private volatile bool running;
}
在Gogogo()中,我想检查running
是否为真,如果是,则从方法返回。但是,如果它是false,我想将其设置为true并继续该方法。我看到的解决方案是执行以下操作:
public class MultiThreadClass
{
public void Gogogo()
{
lock (this.locker)
{
if (this.running)
{
return;
}
this.running = true;
}
// rest of method
this.running = false;
}
private volatile bool running;
private readonly object locker = new object();
}
还有其他办法吗?我发现如果我省略了锁,running
可能对于2个不同的线程是假的,设置为true,并且该方法的其余部分将同时在两个线程上执行。
我想我的目标是让我的方法的其余部分在一个线程上执行(我不关心哪一个)并且不被其他线程执行,即使所有这些都是(在这种情况下为2-4) )同时打电话给Gogogo()。
我也可以锁定整个方法,但方法运行速度会慢吗?它需要尽可能快地运行,但一部分只能在一个线程上运行。
(详细信息:我有一个ConcurrentQueue的词典,其中包含“结果”,其中包含“作业名称”。我试图将每个键中的一个结果出列(每个作业名称一个结果)并将其称为“完整结果” “由事件发送给订阅者。结果通过事件发送到类,并且该事件从多个线程引发(每个作业名称一个;每个作业在其自己的线程上引发”结果就绪“事件)< / p>
答案 0 :(得分:1)
我认为Interlocked.Exchange可以做到这一点。
答案 1 :(得分:1)
如果您 想要
,则可以使用Interlocked
来处理此情况,而不是lock
。
public class MultiThreadClass
{
public void Gogogo()
{
if (Interlocked.Exchange(ref running, 1) == 0)
{
//Do stuff
running = 0;
}
}
private volatile int running = 0;
}
那就是说,除非有一个非常高的争用率(我不指望),那么你的代码应该是完全足够的。使用Interlocked
在可读性部门也会受到一些影响,因为他们的方法没有bool
重载。
答案 2 :(得分:1)
如果将bool更改为int:
,则可以使用Interlocked.CompareExchange
private volatile int running = 0;
if(Interlocked.CompareExchange(ref running, 1, 0) == 0)
{
//running changed from false to true
}
答案 3 :(得分:0)
您需要使用Monitor类而不是boolean标志。使用Monitor.TryEnter:
public void Gogogo()
{
if Monitor.TryEnter(this.locker)
{
try
{
// Do stuff
}
finally
{
Monitor.Exit(this.locker);
}
}
}