Sobes.tech
Middle

Go'da bir programda karşılıklı kilitlenme (deadlock) durumundan nasıl kaçınılır?

sobes.tech yapay zeka

AI'dan gelen yanıt

Go'da karşılıklı kilitlenme genellikle mutexler ve kanalların yanlış kullanımı nedeniyle ortaya çıkar. Aşağıdaki yöntemlerle önlenebilir:

  • Mutexlerin sıralı alınması: Birden fazla mutex alınırken, bunu tüm goroutine'lerde her zaman aynı sırayla yapın.
  • Kilitlemeler için zaman aşımı: Kilitleri beklerken veya kanallardan alırken zaman aşımlı bağlamlar kullanın, böylece sonsuz bekleme önlenir.
  • Bufferlenmemiş kanallar: Bufferlenmemiş kanalların hem gönderen hem de alıcı tarafın devam etmesi gerektiğini anlayın. Yanlış kullanım kilitlenmeye neden olabilir.
  • Bufferli kanallar: Kanalın tampon boyutunu doğru seçin. Çok küçük bir tampon, gönderenler ve alıcılar senkronize değilse kilitlenmeye neden olabilir.
  • select kullanımı: Birden fazla kanal ile çalışırken, select operatörünü default durumu veya zaman aşımı ile kullanın, böylece tek bir kanal beklerken kilitlenmezsiniz.
  • Kodu analiz etme: Statik analiz araçları (go vet, staticcheck) ve yarış koşullarını tespit eden araçlar (go run -race) kullanın, bu araçlar potansiyel karşılıklı kilitlenme noktalarını da tespit edebilir.
  • Kaynak hiyerarşisi: Kaynaklar bir hiyerarşiye sahipse, onları yukarıdan aşağıya doğru alın.
  • Döngüsel bağımlılıkları önleme: A gorutini B'nin tuttuğu kaynağı beklerken, B de A'nın tuttuğu kaynağı beklememelidir.

select ve zaman aşımı ile kullanım örneği:

import (
	"context"
	"time"
)

func örnek(ch chan int) {
	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
	defer cancel()

	select {
	case val := <-ch:
		// Değeri işle
		_ = val
	case <-ctx.Done():
		// Zaman aşımı gerçekleşti
	}
}