Я прочитал довольно много сообщений на эту тему и, кажется, наконец понял, как ключевое слово volatile
работает в C #. Тем не менее, я хотел спросить здесь, чтобы убедиться, что я правильно понимаю концепции. Рассмотрим следующий код:
class ThreadWrapper
{
public bool Enabled { get; set; }
private void ThreadMethod()
{
while (Enabled) { // ... Do work }
}
}
Насколько я понимаю, если другой поток установит Enabled = 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 ++
не является атомарной операцией, но если один поток выполняет все приращения, а другой просто хочет прочитать его, чтобы увидеть, достигает ли он определенного порога, все в порядке, верно?
Edit: Конечно, я нашел еще один подобный вопрос с подробными ответами после факта.