Modül dersleri (4/5)
'sync.Mutex' ve 'sync.WaitGroup'
Kanallar Go'nun birincil deyimidir ancak bazen daha gelenekseldir
ilkellere ihtiyaç var. sync paketi muteksleri sağlar, bekleyin
Paylaşılan durumu koordine etmek için gruplar ve diğer yardımcı programlar.
senkronizasyon.Mutex: özel kilit
import "sync"
type Counter struct {
mu sync.Mutex
count int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.count++
}
func (c *Counter) Get() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}Lock() ve Unlock() arasına aynı anda yalnızca bir goroutin girer.
Zorunlu kalıp: defer mu.Unlock(), Lock()'den hemen sonra.
sink.RWMutex: birçok okuyucu, tek yazar
Okuma ağırlıklı durum için:
var mu sync.RWMutex
mu.RLock() // read lock: più goroutine simultanee OK
v := data
mu.RUnlock()
mu.Lock() // write lock: esclusivo
data = newValue
mu.Unlock()Yalnızca okumaların gerçekten yazmalara üstün gelmesi durumunda kullanışlıdır; aksi takdirde düzenli
sync.Mutex daha düşük dahili hız sayesinde daha basit ve çoğu zaman daha hızlıdır
çekişme.
senkronizasyon.WaitGroup: N goroutine'i bekleyin
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
work(id)
}(i)
}
wg.Wait() // blocca finché tutti i Done() sono arrivatiİş akışı:
wg.Add(N)sayacı N kadar artırır (goroutinleri başlatmadan önce).- Her goroutine bittiğinde
wg.Done()çağırır (ideal olarakdeferaracılığıyla). wg.Wait()sayaç 0'a dönene kadar bloklar.
Sync.Once: iş parçacığı güvenli tembel başlatma
var (
once sync.Once
config *Config
)
func GetConfig() *Config {
once.Do(func() {
config = loadConfig()
})
return config
}once.Do içindeki geri arama tam olarak bir kez, eşzamanlı olarak bile çalışır
Aramalar. Singleton / tembel başlatma modeli.
Mutex vs kanal: ne zaman ne kullanılmalı
Yönergeler (aynı zamanda resmi Go SSS'sinden):
| Durum | Tercih edilen araç |
|---|---|
| Verilerin sahipliğini aktarma | kanal |
| İş dağıtımı (iş kuyruğu) | kanal |
| Bağımsız goroutinlerin koordinasyonu | kanal |
| Yapı alanını koruma | Muteks |
| Önbellek / sayaç | Mutex veya atomik |
| Singleton referansı | sync.Once |
"Düzenlenecek kanallar, paylaşılan veriler için muteksler" iyi bir genel kuraldır.
Yarış dedektörü
Veri yarışlarını tespit etmek için -race ile testler yapın:
go test -race ./...
go run -race main.goYarış detektörü ikili dosyayı yönetir ve senkronize olmayan her şeyi günlüğe kaydeder Paylaşılan hafızaya erişim. Eşzamanlı kodu doğrulamak için 1 numaralı araçtır Üretimden önce.
Deneyin
Sayım artışını mu.Lock() + defer mu.Unlock() ile koruyun.
İpucu göster
defer mu.Unlock(), Lock()'tan hemen sonra panik halinde bile serbest bırakılmasını garanti eder.
3 denemeden sonra çözüm mevcut
3 goroutine başlatın ve sink.WaitGroup (her goroutine'de Add(3), Done(), Wait()) kullanarak hepsini bekleyin.
İpucu göster
Goroutini başlatmadan ÖNCE ekleyin; Erteleme ile Goroutinin İÇİNDE yapılır.
3 denemeden sonra çözüm mevcut
Mutex'in serbest bırakılmasını garanti etmek için önerilen model nedir?
mu.Lock()
// ?Özet
sync.Mutexpaylaşılan durumu korur; her zamandefer mu.Unlock().- Muteksin kopyalanmasını önlemek için bir işaretçi alıcısı kullanın.
- Çok okuyuculu/tek yazarlı kalıplar için
sync.RWMutex(yalnızca yardımcı olması durumunda). sync.WaitGroup:Addöncego,Doneiledefer,Waitbeklemek için.sync.Once: iş parçacığı açısından güvenli tembel başlatma.- "Düzenlenecek kanallar, paylaşılan veriler için muteksler".
go test -race: veri yarışlarını tespit etmek için 1 numaralı araç.