C# 如何在一个原子操作中执行布尔值的读取和写入?
假设我有一个被多个线程调用的方法C# 如何在一个原子操作中执行布尔值的读取和写入?,c#,C#,假设我有一个被多个线程调用的方法 public class MultiThreadClass { public void Gogogo() { // method implementation } private volatile bool running; } 在Gogogo()中,我想检查running是否为true,如果为true,则从该方法返回。但是,如果为false,我希望将其设置为true并继续该方法。我看到的解决方案是执行以下操作
public class MultiThreadClass
{
public void Gogogo()
{
// method implementation
}
private volatile bool running;
}
在Gogogo()中,我想检查running
是否为true,如果为true,则从该方法返回。但是,如果为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();
}
还有别的办法吗?我发现,如果我省略了锁,对两个不同的线程运行
可能是false,设置为true,方法的其余部分将同时在两个线程上执行
我想我的目标是让方法的其余部分在单个线程上执行(我不在乎是哪个线程),而不被其他线程执行,即使所有线程(本例中为2-4个)同时调用Gogogo()
我也可以锁定整个方法,但是该方法会运行得更慢吗?它需要尽可能快地运行,但一次只能在一个线程上运行一部分
(详细信息:我有一个ConcurrentQueue的字典,其中包含有“作业名称”的“结果”。我正在尝试将字典中每个键的一个结果(每个作业名称一个结果)出列,并将其称为“完整结果”由事件发送到订阅服务器。结果通过事件发送到类,该事件从多个线程引发(每个作业名称一个;每个作业在其自己的线程上引发一个“结果就绪”事件)我认为应该这样做。如果您确实想:
也就是说,除非有一个非常高的争用率(这是我不期望的)那么您的代码应该完全足够了。使用
interlocted
也会在可读性方面受到一些影响,因为它们的方法没有bool
重载。您可以使用interlocted。如果将bool更改为int,则比较交换
:
private volatile int running = 0;
if(Interlocked.CompareExchange(ref running, 1, 0) == 0)
{
//running changed from false to true
}
您需要使用Monitor类而不是boolean标志。请使用Monitor.TryEnter:
public void Gogogo()
{
if Monitor.TryEnter(this.locker)
{
try
{
// Do stuff
}
finally
{
Monitor.Exit(this.locker);
}
}
}
你看过
Interlocated
?我想说知道怎么做很酷。但是,几乎可以肯定是微优化。如果你还没有运行代码分析来确定这段代码确实是一个瓶颈,那么一定是微优化。在被证明有罪之前是无辜的。谢谢Servy。为什么Interlocated没有bool重载?看起来它们会很有用(这样我就不必用1
和0
来表示真与假)。@SamPearson谁知道呢。他们只是没有花时间来实现它。这不会导致在另一个方法运行时调用此方法来跳过所请求的方法体。
public void Gogogo()
{
if Monitor.TryEnter(this.locker)
{
try
{
// Do stuff
}
finally
{
Monitor.Exit(this.locker);
}
}
}