ProgrammatieBackend ontwikkelaar

Leg uit wat safe publication in Java is, waarom het nodig is bij multithreading en welke manieren er zijn om het te waarborgen.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Safe Publication (veilige publicatie) is de gegarandeerde veilige verspreiding van een object tussen threads: als één thread een object creëert en initialiseert, zal een andere thread altijd het volledig geconstrueerde object zien en niet de gedeeltelijk geïnitialiseerde toestand.

Zonder safe publication kunnen race conditions optreden: één thread ziet het niet-geinitializeerde deel van het object, zelfs als de constructor al is uitgevoerd.

Manieren om safe publication te waarborgen:

  • Gebruik final-velden — hun waarde is gegarandeerd zichtbaar voor andere threads na de constructor.
  • Publiceer het object via een volatile-variabele of AtomicReference.
  • Publiceer het object via thread-veiliger containers (bijvoorbeeld collecties uit java.util.concurrent).
  • Gebruik synchronized bij het creëren en lezen van het object.

Voorbeeld (onveilig):

public class Holder { private int n; public Holder(int n) { this.n = n; } } Holder holder; void publish() { holder = new Holder(42); } // Veiligheid niet gegarandeerd

Er kunnen niet volledig geconstrueerde objecten zichtbaar zijn!

Voorbeeld (veilig):

volatile Holder holder; void publish() { holder = new Holder(42); } // Lezen van holder zal ook veilig zijn

Vraag met een valstrik

Als alle velden in het object final zijn, garandeert dit dan altijd safe publication?

Antwoord: Nee, alleen als de verwijzing naar het nieuwe object wordt gepubliceerd voordat de constructor is voltooid. Als de verwijzing naar andere threads gaat voordat de constructor is voltooid, kunnen de velden mogelijk niet volledig zijn geïnitialiseerd. Vermijd het publiceert van this of verwijzingen naar niet volledig geconstrueerde objecten tijdens de uitvoering van de constructor.

Voorbeeld (gevaarlijk!):

public class PublishEscape { public static PublishEscape instance; public PublishEscape() { instance = this; // Slecht! this wordt gepubliceerd voordat de constructor is voltooid } }

Geschiedenis

Een ontwikkelaar wijsde een verwijzing naar een Service-instantie toe in een veld dat toegankelijk was via static, voordat de constructor was voltooid. Als gevolg hiervan ontving een andere thread een gedeeltelijk geconstrueerd object, wat onvoorspelbaar gedrag in productie veroorzaakte.


Geschiedenis

In een webapplicatie werden singleton-objecten gecreëerd zonder extra synchronisatie. Onder belasting ontvingen sommige threads null of onjuist geïnitialiseerde velden, wat leidde tot Intermittent NullPointerException.


Geschiedenis

In de bibliotheek werd een gewone List gebruikt voor caching tussen threads — er ontbrak safe publication, en initialisatie garandeerde niet zichtbaar te zijn voor nieuwe threads. Uiteindelijk werkte de cache chaotisch, wat de gegevensintegriteit verstoorde.