GoDasturchi
Race Detection and Data Races

Race Detection and Data Races

Poyga sharoitini aniqlash va data race'lar

Ushbu kurs davomida siz bir necha marta "poyga sharoiti (race condition)" iborasini uchratdingiz. Aniq ta'rif: data race — ikki yoki undan ko'p goroutina bitta xotira joyiga bir vaqtda murojaat qilib, kamida bittasi yozayotgan, va ular orasida hech qanday sinxronlash (Mutex, kanal) yo'q bo'lgan holat.

Data race'ning eng xavfli tomoni — u ko'pincha jim ishlaydi: dastur odatda to'g'ri natija beradi, lekin vaqti-vaqti bilan, bashorat qilib bo'lmaydigan tarzda noto'g'ri natija yoki hatto qulash (crash) beradi. Shuning uchun Go maxsus vosita bilan keladi — race detector, -race bayrog'i orqali yoqiladi:

example.go
go run -race main.go
go test -race ./...

Race detector dasturni ishga tushirib, xotiraga barcha kirishlarni kuzatadi va sinxronlashsiz umumiy kirishni aniqlasa, aniq qaysi qatorlar mojaro qilayotganini ko'rsatadi. Bu — DNS Resolver kursidagi Cycle Detection darsiga o'xshaydi: ikkalasi ham "ko'zga tashlanmaydigan, lekin halokatli" muammoni tizimli ravishda aniqlash haqida.

Yechim har doim bir xil: umumiy xotirani sync.Mutex bilan himoyalash, yoki umuman umumiy xotiradan voz kechib, Channels darsidagi kabi muloqot orqali ma'lumot uzatish. Quyidagi misol — bir nechta goroutina bir xil mapga bir vaqtda yozganda nima uchun Mutex shart ekanini ko'rsatadi (Go'da xom map'ga concurrent yozish hatto dasturni qulatishi mumkin):

example.go
counts := make(map[string]int)
var mu sync.Mutex
var wg sync.WaitGroup

for _, w := range words {
    wg.Add(1)
    go func(word string) {
        defer wg.Done()
        mu.Lock()
        counts[word]++
        mu.Unlock()
    }(w)
}
wg.Wait()

>_ Exercise

ConcurrentWordCount(words []string) map[string]int funksiyasini yozing. Har bir so'z uchun alohida goroutina ishga tushiring — u umumiy counts map'idagi shu so'zning sonini bittaga oshiradi, sync.Mutex bilan himoyalab (Go'da xom map'ga concurrent yozish xavfsiz emas). sync.WaitGroup bilan barcha goroutinalar tugashini kutib, to'liq counts map'ini qaytaring.

Stuck? Reveal a hint to help you.

Hints (0/4)

Key Takeaway

Key Takeaway:

Data race — sinxronlashsiz umumiy xotiraga concurrent kirish, va u ko'pincha faqat vaqti-vaqti bilan namoyon bo'ladi. go run -race / go test -race bunday muammolarni ishga tushirish vaqtida aniqlaydi. Yechim har doim bir xil: umumiy holatni Mutex bilan himoyalang, yoki uni umuman umumiy qilmasdan, kanal orqali muloqot qiling.

Finish
OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Race Detection and Data Races

Poyga sharoitini aniqlash va data race'lar

Ushbu kurs davomida siz bir necha marta "poyga sharoiti (race condition)" iborasini uchratdingiz. Aniq ta'rif: data race — ikki yoki undan ko'p goroutina bitta xotira joyiga bir vaqtda murojaat qilib, kamida bittasi yozayotgan, va ular orasida hech qanday sinxronlash (Mutex, kanal) yo'q bo'lgan holat.

Data race'ning eng xavfli tomoni — u ko'pincha jim ishlaydi: dastur odatda to'g'ri natija beradi, lekin vaqti-vaqti bilan, bashorat qilib bo'lmaydigan tarzda noto'g'ri natija yoki hatto qulash (crash) beradi. Shuning uchun Go maxsus vosita bilan keladi — race detector, -race bayrog'i orqali yoqiladi:

example.go
go run -race main.go
go test -race ./...

Race detector dasturni ishga tushirib, xotiraga barcha kirishlarni kuzatadi va sinxronlashsiz umumiy kirishni aniqlasa, aniq qaysi qatorlar mojaro qilayotganini ko'rsatadi. Bu — DNS Resolver kursidagi Cycle Detection darsiga o'xshaydi: ikkalasi ham "ko'zga tashlanmaydigan, lekin halokatli" muammoni tizimli ravishda aniqlash haqida.

Yechim har doim bir xil: umumiy xotirani sync.Mutex bilan himoyalash, yoki umuman umumiy xotiradan voz kechib, Channels darsidagi kabi muloqot orqali ma'lumot uzatish. Quyidagi misol — bir nechta goroutina bir xil mapga bir vaqtda yozganda nima uchun Mutex shart ekanini ko'rsatadi (Go'da xom map'ga concurrent yozish hatto dasturni qulatishi mumkin):

example.go
counts := make(map[string]int)
var mu sync.Mutex
var wg sync.WaitGroup

for _, w := range words {
    wg.Add(1)
    go func(word string) {
        defer wg.Done()
        mu.Lock()
        counts[word]++
        mu.Unlock()
    }(w)
}
wg.Wait()

>_ Exercise

ConcurrentWordCount(words []string) map[string]int funksiyasini yozing. Har bir so'z uchun alohida goroutina ishga tushiring — u umumiy counts map'idagi shu so'zning sonini bittaga oshiradi, sync.Mutex bilan himoyalab (Go'da xom map'ga concurrent yozish xavfsiz emas). sync.WaitGroup bilan barcha goroutinalar tugashini kutib, to'liq counts map'ini qaytaring.

Stuck? Reveal a hint to help you.

Hints (0/4)

Key Takeaway

Key Takeaway:

Data race — sinxronlashsiz umumiy xotiraga concurrent kirish, va u ko'pincha faqat vaqti-vaqti bilan namoyon bo'ladi. go run -race / go test -race bunday muammolarni ishga tushirish vaqtida aniqlaydi. Yechim har doim bir xil: umumiy holatni Mutex bilan himoyalang, yoki uni umuman umumiy qilmasdan, kanal orqali muloqot qiling.