ProgramlamaBackend Geliştirici

Java'da safe publication nedir, çoklu iş parçacığında neden gereklidir ve nasıl sağlanır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

Safe Publication (güvenli yayınlama) — bir nesnenin iş parçacıkları arasında güvenli bir şekilde dağıtılmasını garantileyen bir mekanizmadır: bir iş parçacığı bir nesne oluşturup başlatırsa, diğer iş parçacığı her zaman tamamen yapılandırılmış nesneyi görür, yarı yapılandırılmış durumunu değil.

Safe publication olmadan race condition'lar ortaya çıkabilir: bir iş parçacığı, konstrüktör çalıştıktan sonra bile, nesnenin henüz başlatılmamış bir kısmını görebilir.

Safe publication’ı sağlamanın yolları:

  • final alanlarını kullanmak — bu alanların değeri, konstrüktörden sonra diğer iş parçacıkları için garanti edilir.
  • Nesneyi volatile değişken veya AtomicReference üzerinden yayınlamak.
  • Nesneyi thread-safe konteynerlar (örneğin, java.util.concurrent koleksiyonları) üzerinden yayınlamak.
  • Nesne oluşturulurken ve okunurken synchronized kullanmak.

Örnek (unsafe):

public class Holder { private int n; public Holder(int n) { this.n = n; } } Holder holder; void publish() { holder = new Holder(42); } // Güvenlik garanti edilmez

Tamamen yapılandırılmamış nesneler görünür olabilir!

Örnek (safe):

volatile Holder holder; void publish() { holder = new Holder(42); } // holder'ı okumak da güvenli olacaktır

Kandırmaca Soru

Eğer nesnede tüm alanlar final ise, bu her zaman safe publication'ı garanti eder mi?

Cevap: Hayır, sadece yeni nesneye olan referans konstrüktörün tamamlanmasından önce yayınlanırsa. Eğer referans, konstrüktör tamamlanmadan diğer iş parçacıklarına aktarılırsa, alanlar tam olarak başlatılmamış olabilir. Konstrüktör çalışırken 'this' veya tamamlanmamış nesnelere referans yayınlamaktan kaçınılmalıdır.

Örnek (tehlikeli!):

public class PublishEscape { public static PublishEscape instance; public PublishEscape() { instance = this; // Kötü! this konstrüktörün tamamlanmasından önce yayınlanıyor } }

Hikaye

Geliştirici, konstrüktör tamamlanmadan önce statik bir alanda Service örneğine referans veriyordu. Sonuç olarak, diğer bir iş parçacığı yarı yapılandırılmış bir nesne aldı ve bu üretimde öngörülemeyen davranışlara yol açtı.


Hikaye

Web uygulamasında singleton nesneleri ek bir senkronizasyon olmadan oluşturuldu. Yük altında bazı iş parçacıkları null veya yanlış bir şekilde başlatılmış alanlar aldı ve bu da Intermittent NullPointerException'a neden oldu.


Hikaye

Kütüphanede iş parçacıkları arasında cache için normal bir List kullanıldı — safe publication eksikti, başlatma yeni iş parçacıkları için görünürlük sağlamıyordu. Sonuç olarak, cache kaotik bir şekilde çalıştı ve veri bütünlüğünü ihlal etti.