Пытаемся понять модель памяти .net, когда дело касается потоковой передачи. Это чисто теоретический вопрос, и я знаю, что его можно решить другими способами, например, используя lock
или пометив _task
как volatile
.
Возьмем, к примеру, следующий фрагмент кода:
class Test
{
Task _task;
int _working = 0;
public void Run()
{
if (Interlocked.CompareExchange(ref _working, 1, 0) == 0)
{
_task = Task.Factory.StartNew(() =>
{
//do some work...
});
_task.ContinueWith(antecendent => Interlocked.Exchange(ref _working, 0));
}
}
public void Dispose()
{
if (Interlocked.CompareExchange(ref _working, _working, 0) == 1)
{
_task.ContinueWith(antecendent => { /*do some other work*/ });
}
}
}
Теперь сделайте следующие предположения:
Run
может вызываться несколько раз (из разных потоков) и никогда не будет вызван после вызоваDispose
.Dispose
будет вызываться ровно один раз.
Теперь к моему вопросу, всегда ли значение _task
(в методе Dispose
) будет «свежим» значением, то есть будет ли оно считываться из «основной памяти», а не из регистра? Из того, что я читал, Interlocked
создает полный барьер памяти, поэтому я предполагаю, что _task
будет считываться из основной памяти, или я полностью отключен?