我读了不少关于这个主题的文章,我认为我终于理解了在C#中如何使用volatile
关键字。但我还是想在这里问一下,以确保我正确地理解了这些概念。请考虑以下代码:
class ThreadWrapper
{
public bool Enabled { get; set; }
private void ThreadMethod()
{
while (Enabled) { // ... Do work }
}
}
据我所了解,如果另一个线程将
Enabled=false
设置为 false,则原始线程可能无法立即(或永远)看到此更改。为确保编译器不会优化对 Enabled 属性的访问并依赖缓存值,更改代码如下应该可以解决问题。 public bool Enabled { get {return mEnabled;} set {mEnabled=value;} }
private volatile bool mEnabled;
现在,每当读取Enabled值时,它都保证获取到最新的值,是吗?如果是这样,我应该能够将其用作简单的信号或标志(如上所述)。
另一个例子是:
class C
{
private volatile int i;
private volatile bool enabledA;
private volatile bool enabledB;
void ThreadA()
{
i = 0; // Reset counter
while (enabledA)
{
// .. Do some other repeated work
if (i > 100)
{
// .. Handle threshold case
}
}
}
void ThreadB()
{
while (enabledB)
{
// .. Do work
if (condition) // Some condition occurs that we want to count
{
i++;
}
}
}
}
对于像这样的简单线程间通信,
volatile
是否足够?我知道 i++
不是原子操作,但如果一个线程在做所有递增,而另一个线程只是想读取它以查看是否达到了某个阈值,那么我们没问题,对吗?编辑:在事后我当然找到了另一个类似的问题及其详细答案。