Imagine a kitchen (the process). Cooks are threads — they all share the same fridge, counter, and ingredients (shared memory), but each cook has their own little chopping board (stack).
Now, who tells cooks when to work?
If the head chef inside the kitchen does it (user-level), the manager of the whole restaurant (kernel) thinks the kitchen is just one worker. So if one cook goes to the freezer in the basement and gets stuck (a blocking call), the manager thinks the whole kitchen stopped and gives the stove to a different kitchen — even though other cooks were ready!
If the restaurant manager schedules each cook directly (kernel-level), only the stuck cook waits; the rest keep cooking — and they can use many stoves at once (cores). But asking the manager for every little thing is slow.
Many-to-Many: have a few cooks the manager knows about, and let extra helpers share those slots — fast and nobody freezes the whole kitchen.
Dekho, ek process ek ghar jaisa hai aur threads us ghar ke andar ke workers hain. Saare workers same fridge, same saaman (address space, code, data, files) share karte hain, par har worker ka apna chopping board hota hai — yaani apna stack aur registers. Isi sharing ki wajah se threads banana aur switch karna sasta hota hai, aur multi-core CPU par ye sach much parallel chal sakte hain.
Asli sawal yeh hai: in workers ko schedule kaun karta hai? Agar user-level library karti hai (user-level threads), to kernel ko lagta hai poori process bas ek hi banda hai. Problem yeh: agar ek thread ne blocking system call (jaise read()) maari, to kernel poori process ko block kar deta hai — baaki ready threads bhi atak jaate hain, aur multi-core ka fayda bhi nahi milta. Agar kernel schedule karta hai (kernel-level threads), to sirf wahi thread blocks hota hai, baaki chalte rehte hain, aur true parallelism milta hai — par har create/switch ek system call hai, thoda slow.
Mapping ke teen models yaad rakho: Many-to-One = bahut user threads ek kernel thread par → ek block karega to sab freeze, no parallelism. One-to-One = har user thread ka apna kernel thread → fast aur parallel, par kernel par bojh (Linux/Windows yahi use karte hain). Many-to-Many = m user threads ko n (n ≤ m) kernel threads par map karo → sasta bhi aur parallel bhi, best balance (jaise Go goroutines).
Mantra: "M1 freezes, 1:1 flies, MN balances." Aur galti se mat sochna ki threads ke alag address space hote hain — nahi, sirf stack aur registers private hote hain, baaki sab shared, isliye locks ki zaroorat padti hai.