Middle
Go'da mutexlerle çalışırken neyi hatırlamak gerekir?
sobes.tech yapay zeka
AI'dan gelen yanıt
Go dilinde (sync.Mutex) mutexlerle çalışırken aşağıdakileri hatırlamak önemlidir:
- Kilit ve serbest bırakma: Mutex mutlaka (
Lock()) paylaşılan verilere erişmeden önce kilitlenmeli ve iş tamamlandıktan sonra (Unlock()) serbest bırakılmalıdır.defer mu.Unlock()kullanımı,mu.Lock()hemen ardından, unutmayı önlemek için iyi bir uygulamadır. - Özel erişim: Mutex, aynı anda yalnızca bir goroutine'un kaynağa erişmesine izin verir.
- "Kilitleme/açma" durumu: Bir mutex zaten kilitliyken tekrar
Lock()çağrısı, çağıran goroutine'in başka bir goroutine serbest bırakana kadar bloke olmasına neden olur. Kilitli olmayan bir mutex üzerindeUnlock()çağrısı ise çalışma zamanında panik oluşturur. - Mutexleri kopyalamayın:
sync.Mutexyapısı, ilk kullanım sonrası kopyalanmak üzere tasarlanmamıştır. Bir mutex'i değeriyle geçirmek veya mutex içeren yapıyı kopyalamak, yanlış senkronizasyon ve paniklere yol açabilir. - Deadlock (ölüm kilidi): İki veya daha fazla goroutine'un birbirlerinin serbest bırakmasını beklediği durumdur. Tipik senaryo: A goroutine'u R1'i kilitler ve R2'yi bekler, B goroutine'u R2'yi kilitler ve R1'i bekler.
- Livelock (canlı kilit): Goroutine'ların sürekli durum değiştirerek birbirlerinin hareketlerine yanıt verdiği, ancak işe yaramaz işler yaptığı ve ilerlemediği durumdur. Deadlock'tan daha az rastlanır.
- Açlık (starvation): Bir veya birkaç goroutine'un, diğerleri sürekli olarak kilitlediği için paylaşılan kaynağa erişemediği durumdur. Go mutex'lerinde açlık garantilenmez.
sync.RWMutexkullanımı: Çoğu işlem okuma ise ve yazma nadiren yapılacaksa,sync.RWMutexdaha verimli olabilir. Aynı anda birden fazla okuma yapılmasına izin verir, ancak yazma sırasında tüm okuma ve yazma işlemlerini engeller.- Kısa kilitler: Kilitleri mümkün olan en kısa sürede tutmaya çalışın. Mutex uzun süre kilitli kalırsa, diğer goroutine'lar bekler ve paralellik azalır.
- Yarış durumu testi:
-racebayrağı kullanmak, derleme ve test çalıştırırken (go test -race) yarış durumlarını tespit etmeye yardımcı olur.
defer kullanımı örneği:
import (
"sync"
)
type SafeCounter struct {
mu sync.Mutex
v map[string]int
}
// Inc, anahtar için sayacı güvenli bir şekilde artırır.
func (c *SafeCounter) Inc(key string) {
c.mu.Lock()
// Fonktan çıkarken serbest bırakmayı erteleyin.
defer c.mu.Unlock()
c.v[key]++
}
// Value, anahtar için mevcut sayacı döndürür.
func (c *SafeCounter) Value(key string) int {
c.mu.Lock()
// Değer alınana kadar serbest bırakılır.
defer c.mu.Unlock()
return c.v[key]
}