Parent note Memory Model padhne se pehle, tumhe har woh word aur symbol chahiye jo woh silently assume karta hai. Hum unhe ek ek karke build karte hain, zero se, har ek pichle ke upar.
Figure dekho: do shelves (do CPU cores), aur har ek par boxes. Asli problem — jis par yeh poora topic hai — yeh hai ki jab core 1 koi box change karta hai, core 2 woh change instantly nahi dekhta. Ek delay hoti hai, jo unke beech wavy pipe ke roop mein draw ki gayi hai.
Picture: do log (Thread 1, Thread 2) har ek ke paas ek to-do list, dono same boxes tak pahunch rahe hain. Is topic mein jo bhi mushkil hai woh isliye hota hai kyunki woh memory share karte hain lekin apni apni pace se chalta hai.
Topic ko iska kyun zaroorat hai: data race, happens-before, acquire, release — yeh sab do threads ke beech relationships describe karte hain. Ek thread ke saath koi problem hi nahi hoti.
Picture: ek arrow seedha to-do list ke neeche point karta hua. Yeh woh order hai jo tumne likha, zaroorat nahi ki machine kare bhi usi order mein — jo agle symbol ka poora surprise hai.
Figure mein black arrow woh order hai jo tumne likha; red arrow ek aisa order hai jo machine actually run kar sakti hai. Teen alag villains yeh swap cause kar sakte hain:
compiler (dekho Compiler reordering and the as-if rule),
Picture: solid lid wala ek box, taaki koi bhi andar dekhe toh ya purani value dekhe ya nayi value, kabhi smeared mix nahi. Important aur miss karna aasaan hai: atomic yeh guarantee sirf us atomic box khud ke liye deta hai — abhi tak woh surrounding ordinary boxes ke baare mein kuch nahi kehta. Unhe order karna ek alag kaam hai (iske liye §9–11 hain).
Topic ko iska kyun zaroorat hai: poora memory model isliye exist karta hai taaki tum data races avoid kar sako missing ordering arrow supply karke. Yahan se sab kuch us arrow ko sahi tarike se banane ke baare mein hai.
Hume yeh do words cross-thread arrow define karne se pehle milne chahiye, kyunki woh arrow inhi se bana hai.
Figure mein release ek floor ke roop mein hai (⬇ cheezein neeche nahi gir sakti) aur acquire ek ceiling ke roop mein (⬆ cheezein upar nahi ja sakti). Ek saath, jab acquire-load exactly wahi value padhta hai jo release-store ne likhi, ek handshake banta hai — agli section ka cross-thread arrow.
Ek mutex bas yeh dono chipke hue hain: locking acquire hai, unlocking release hai.
Yahan "event" ka matlab bas ek read ya write hona hai. Hum events ko arrows se jodte hain. Pehle, notation ke do chhote tukde taaki arrows clearly padhe ja saken:
AhbB⟹B sees every write done by A
Woh formula payoff hai. Agar — aur sirf tab — tum ek write se ek read tak happens-before path draw kar sako, toh read guaranteed hai ki woh write dekhega. Koi path nahi ⇒ koi guarantee nahi ⇒ possible data race.
Figure follow karo: solid down-arrows sequenced-before hain, dashed cross-arrow synchronizes-with hai, aur (1) se (4) tak lamba green path woh happens-before chain hai jo data == 42 ko safe banata hai.
Picture: ek dial "loose" (relaxed) se "strict" (seq_cst) tak. Zyada strictness = zyada guarantees = usually slower, kyunki CPU ko real fences insert karne padte hain (dekho std-atomic_thread_fence).
Har foundation agli ko feed karta hai; do arrows jo finally Happens-before par milte hain wahi poora point hai — ek thread ke andar se (sequenced-before), ek threads ke across (synchronizes-with).