Fix yeh hai: ek single CPU instruction jo old value read kare AUR new value ek atomic, uninterruptible step mein likhe, bus lock ke saath taaki koi aur core beech mein ghus na sake.
WHY yeh correct hai.test_and_set hamesha lock = 1 set karta hai. Return value batati hai ki woh pehle kya tha:
Agar old value 0 thi → lock free tha, aur humne abhi ise claim kar liya. Loop exit karta hai → humara hai.
Agar old value 1 thi → koi pehle se hold kar raha tha; humne ise phir se 1 set kar diya (harmless, woh already 1 tha) aur spin karte rahe.
"Check" (read old) aur "claim" (write 1) ab ek indivisible action hain, toh upar wali race ho hi nahi sakti. Read aur write ke beech koi window nahi hai jahan koi doosra thread ghus sake.
WHY CAS > TAS. TAS sirf ek boolean manipulate kar sakta hai. CAS tumhe kehne deta hai "X ko tabhi change karo jab woh wahi value ho jo maine last dekhi thi." Yeh lock-free data structures (counters, stacks, queues) enable karta hai, sirf mutexes nahi. Yeh AtomicInteger.compareAndSet, std::atomic::compare_exchange, etc. ki foundation hai.
Why can't a plain while(lock){} lock=1 implement a mutex?
lock ka read aur write do alag instructions hain; beech mein context switch do threads ko dono "free" dekhne deta hai aur dono andar aa jaate hain — mutual exclusion toot jaati hai.
What does test_and_set(addr) do atomically?
addr par old value read karta hai, *addr = 1 set karta hai, old value return karta hai — sab ek indivisible step mein.
In a TAS spinlock, what does a returned old value of 0 mean?
Lock free tha aur tumne abhi ise acquire kar liya; spin loop se bahar niklo.
What does compare_and_swap(addr, expected, new) do?
Atomically: agar *addr == expected ho, toh *addr = new set karo aur true return karo; warna chhod do aur false return karo.
Why is CAS more powerful than test-and-set?
CAS write ko current value ke expected value se match hone par condition karta hai, lock-free data structures enable karta hai; TAS sirf ek boolean flip karta hai.
What is the ABA problem?
Ek CAS succeed ho jaati hai kyunki value expected ke barabar hai, lekin woh actually beech mein A→B→A change ho chuki thi; CAS intermediate change detect nahi kar sakta. Version tags se fix karo.
Why does Test-and-Test-and-Set reduce bus traffic?
Yeh saste cached read par spin karta hai aur expensive atomic RMW sirf tab karta hai jab lock free lagta ho, cache-line bouncing se bachata hai.
Is busy-wait spinning always bad?
Nahi — bahut chote critical sections ke liye multi-core par, spinning context-switch overhead se bachata hai aur sleeping se tez hota hai.
Why is volatile insufficient for a lock flag?
Yeh compiler caching toh rok deta hai lekin atomic read-modify-write ya memory-ordering guarantees nahi deta.
What memory ordering does acquire/release need?
Acquire ko acquire barrier chahiye (koi baad wala op usse pehle na move ho); release ko release barrier chahiye (koi pehle wala op uske baad na move ho) taaki critical-section writes unlock se pehle visible hon.
Recall Feynman: 12-saal ke bacche ko explain karo
Socho ek bathroom hai aur darwaze par ek sign hai jo kehta hai FREE ya BUSY. Agar do bacche sign ko ek hi pal dekhein, dono FREE dekhte hain aur dono barge in karte hain — chaos. Trick: ek jadui darwaze ka handle jo, ek snap mein, sign dekhta bhi hai AUR use BUSY kar deta hai, phir batata hai sign pehle kya keh raha tha. Agar FREE keh raha tha, tum andar aa gaye. Agar BUSY keh raha tha, koi tumse pehle aa gaya — bahar ruko. Kyunki dekhna aur flip karna ek saath hota hai bina kisi gap ke, do bacche kabhi dono nahi jeet sakte. Woh jadui handle "test-and-set" hai. Ek fancier handle ("CAS") sign ko BUSY tabhi karta hai jab woh exactly FREE ho — jo tumhe bina full lock ke shared cheezein safely change karne deta hai.