Tarkibga o'tish

8. Sinxronizatsiya va context

sync paketi (Mutex, RWMutex, Once, WaitGroup, Cond), sync/atomic va context paketlari bilan ishlash. Barcha masalalarni -race bayrog'i bilan tekshiring.

Mutex va atomik amallar

1. 1000 ta goroutine umumiy hisoblagichni 1000 martadan oshirsin. Sinxronizatsiyasiz natija nega 1 000 000 bo'lmasligini ko'rsating, so'ng sync.Mutex bilan tuzating.
Misol: 1000 goroutine × 1000 → sinxronizatsiyasiz natija odatda 1000000 dan kichik (masalan 987342); Mutex bilan har doim 1000000

2. Xuddi shu hisoblagichni atomic.Int64 bilan amalga oshiring va Mutex varianti bilan tezligini time.Since yordamida o'lchab solishtiring.
Misol: atomic.Int64 bilan natija 1000000; vaqt (time.Since) odatda Mutex variantidan kam

3. Xavfsiz map: SafeMap[K comparable, V any] turini sync.RWMutex bilan yozing; o'qish amallari parallel bajarilishi mumkinligini ko'rsating.
Misol: Set("a", 1), Get("a") → 1 true; Get("b") → 0 false; bir nechta goroutine bir vaqtda Get qila oladi

4. sync.Map dan foydalanib kesh yozing va uni oddiy map + RWMutex varianti bilan solishtiring: qaysi holatlarda sync.Map qulayroq?
Misol: Store("k", 1), Load("k") → 1 true; sync.Map ko'p o'qish va kam yozish yoki har bir goroutine o'z kalitlari bilan ishlaganda qulay

5. Ikki hisob orasida pul o'tkazish: ikkita Mutex ni har doim bir xil tartibda qulflab, o'zaro blokirovkaning (deadlock) oldini oling. Noto'g'ri tartibda qulflash deadlock'ga olib kelishini ko'rsating.
Misol: A → B va B → A bir vaqtda, har doim kichik ID dagi hisob oldin qulflanadi → deadlock yo'q; teskari tartibda → fatal error: all goroutines are asleep - deadlock!

6. Mutex'ni qiymat bo'yicha nusxalash xatosini go vet bilan aniqlang va tuzating.
Misol: func f(m sync.Mutex) → go vet: f passes lock by value; to'g'ri variant: func f(m *sync.Mutex)

Once, WaitGroup, Cond, Pool

7. sync.Once bilan faqat bir marta ishga tushadigan konfiguratsiya yuklovchi yozing; 100 ta goroutine uni bir vaqtda chaqirsa ham yuklash bir marta bajarilsin.
Misol: 100 ta goroutine Load() ni chaqirsa → «konfiguratsiya yuklandi» xabari 1 marta chiqadi

8. sync.OnceValue yordamida qimmat hisob-kitob natijasini dangasa (lazy) tarzda keshlang.
Misol: f := sync.OnceValue(func() int { return qimmatHisob() }): f() birinchi chaqirilganda hisoblaydi, keyingilarda tayyor natijani qaytaradi

9. sync.WaitGroup ni noto'g'ri ishlatish holatlarini ko'rsating (Add ni goroutine ichida chaqirish, WaitGroup ni qiymat bo'yicha uzatish) va to'g'ri variantini yozing.
Misol: wg.Add(1) ni goroutine ichida chaqirish → Wait() erta qaytishi mumkin; wg qiymat bo'yicha uzatilsa — nusxa ustida ishlanadi (go vet ogohlantiradi); to'g'ri: Add goroutine'dan oldin, *sync.WaitGroup uzatiladi

10. sync.Cond bilan cheklangan hajmli navbat yozing: navbat to'la bo'lsa yozuvchi, bo'sh bo'lsa o'quvchi kutsin.
Misol: sig'im 2: yozuvchi 1 2 3 4 ni yozadi, o'quvchi sekin o'qiydi → yozuvchi navbat to'lganda kutadi; o'quvchi 1 2 3 4 ni shu tartibda oladi

11. sync.Pool yordamida bytes.Buffer larni qayta ishlating va ko'p marta bufer ajratadigan kodga nisbatan bajarilish vaqtini time.Since bilan va xotira ajratishlar sonini runtime.ReadMemStats bilan solishtiring.
Misol: sync.Pool bilan bytes.Buffer ajratishlar soni (Mallocs) pool'siz variantdan sezilarli kam

12. Kitobxonlar-yozuvchilar masalasi: ko'p o'quvchi va kam yozuvchi bo'lgan holatda RWMutex va oddiy Mutex samaradorligini time.Since bilan o'lchab solishtiring.
Misol: 100 o'quvchi va 2 yozuvchi: RWMutex odatda oddiy Mutex dan tezroq (aniq vaqt kompyuterga bog'liq)

context

13. context.WithCancel yordamida uzoq ishlaydigan goroutine'ni tashqaridan to'xtating; goroutine ctx.Done() ni tekshirib, toza yakunlansin.
Misol: cancel() chaqirilgach goroutine «to'xtatildi» deb chiqadi va tugaydi

14. context.WithTimeout bilan sekin funksiya chaqiruviga 500 ms muddat qo'ying. Muddat tugaganda ctx.Err() qiymatini (context.DeadlineExceeded) chiqaring.
Misol: WithTimeout(ctx, 500*time.Millisecond), funksiya 2 s ishlasa → context deadline exceeded

15. Ota context bekor qilinganda barcha bola context'lar ham bekor bo'lishini uch darajali daraxt misolida ko'rsating.
Misol: root bekor qilinsa → child1, child2, grandchild ning ctx.Err() → context canceled

16. context.WithValue bilan so'rov identifikatorini funksiyalar zanjiri bo'ylab uzating. Kalit uchun alohida tur ishlatish nega muhimligini izohlang.
Misol: WithValue(ctx, requestIDKey{}, "abc-123") → zanjirning oxirida ctx.Value(requestIDKey{}) → abc-123

17. Ishchilar hovuzini context bilan to'xtatiladigan qilib yozing: bekor qilinganda barcha ishchilar yakunlansin va tugallanmagan vazifalar soni chiqarilsin.
Misol: 10 ta vazifa, 3 ishchi, ctx 3 ta vazifadan keyin bekor qilinsa → «tugallanmagan vazifalar: 7»

18. context.AfterFunc yoki context.WithCancelCause dan foydalanib, bekor qilish sababini qayd eting va chiqaring.
Misol: cancel(errors.New("foydalanuvchi to'xtatdi")) → context.Cause(ctx) → foydalanuvchi to'xtatdi

Amaliy masalalar

19. Parallel veb-krauler: «Goroutine va kanallar» mavzusining 26-masalasidagi Fetcher interfeysi va sahifa → havolalar ro'yxatini qaytaruvchi soxta «internet» dan foydalanib, sahifalarni rekursiv aylanib chiqing. Bir URL'ni ikki marta yuklamaslik uchun Mutex bilan himoyalangan visited to'plamidan foydalaning; chuqurlik va parallellik chegaralangan bo'lsin.
Misol: kichik soxta internet: / → [/a, /b], /a → [/], /b → [] → /, /a, /b har biri bir marta yuklanadi

20. Tokenlar chelagi (token bucket) algoritmi asosidagi tezlik cheklovchi yozing: Mutex bilan himoyalangan holat, Allow() bool metodi va parallel so'rovlar bilan sinov.
Misol: sig'im 3, to'ldirish 1/s: dastlabki 3 ta so'rov true, 4-so'rov darhol false, 1 s dan keyin true