Runtime & concurrency
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Reflection;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
int data = 0, ready = 0;
data = 37;
Volatile.Write(ref ready, 1);
if (Volatile.Read(ref ready) != 1) throw new InvalidOperationException();
Console.WriteLine($"value:{data}");
Console.WriteLine($"ready:{Volatile.Read(ref ready)}");
Reveal answer and reasoning
The program prints value:37 and ready:1. It stores thirty-seven in data, publishes one to ready through Volatile.Write, then observes that flag through Volatile.Read before printing the data. In this portable snippet all those actions happen in one flow, so the output does not depend on a competing thread or a scheduling assumption.
The desktop experiment separately applies the publication protocol across actual owned producer and consumer threads and checks the same stable values after they finish. A common wrong trace interprets the sequential output as evidence that a cache was flushed or that a race was reproduced. Removing volatile and seeing the same numbers in one run would not prove the general cross-thread protocol remains correct.
The snippet establishes a real API sequence with narrow scope, not a benchmark, fairness claim, or reusable multi-generation state channel.
What a strong answer covers
- Data is assigned before the ready flag.
- The observed values are thirty-seven and one.
- This companion creates no concurrent producer or consumer.
Common pitfall
Claiming cross-thread memory-order evidence from the sequential companion alone.
Follow-up questions
- What changes when data is fifty?
- Why can removing synchronization appear harmless in a short test?
Self-review
Choose what to revisit. These marks are your own assessment and are separate from lesson completion.