Synchronized: wat is het, werkingsprincipe en gebruik in Java

Auteur: IT Sectr Gepubliceerd: 2026-03-19 Leestijd: 8 min

Synchronized is een ingebouwd synchronisatiemechanisme in de programmeertaal Java, dat exclusieve toegang tot kritieke codegedeelten biedt. Volgens Oracle, 2024 garandeert de modifier synchronized dat slechts één thread de gemarkeerde methode of blok op een bepaald moment kan uitvoeren. Dit mechanisme is gebaseerd op monitoren — een fundamenteel concept van besturingssystemen dat de correcte werking van multithreadingtoepassingen op alle niveaus van complexiteit waarborgt.

Belangrijkste punten

  • Synchronized — Java-sleutelwoord voor threadveilige toegang tot gegevens.
  • Objectmonitor — het interne mechanisme waarop synchronisatie is gebaseerd.
  • Synchronized methode blokkeert de gehele methode op instantie- of klasniveau.
  • Synchronized blok maakt synchronisatie van slechts een deel van de code mogelijk.
  • Deadlock — een van de belangrijkste problemen bij geneste synchronisatie.

Wat is synchronized?

Synchronized is een sleutelwoord in Java dat garandeert dat slechts één thread tegelijk het beschermde codegedeelte uitvoert, waardoor beschadiging van gegevens bij parallelle toegang wordt voorkomen. Het verscheen in de eerste versie van Java en blijft de eenvoudigste manier om threadveiligheid te waarborgen voor ontwikkelaars van elk niveau.

Definitie en rol in Java

De modifier synchronized lost twee taken op: wederzijdse uitsluiting (mutual exclusion) en zichtbaarheid van wijzigingen (visibility). Wanneer een thread een synchronized blok verlaat, zijn alle wijzigingen gegarandeerd zichtbaar voor andere threads die het blok betreden dat op hetzelfde object is gesynchroniseerd.

Synchronized kan worden toegepast op de gehele methode of op een willekeurig codeblok met opgave van het monitor-object. In beide gevallen plaatst de JVM de instructies monitorenter en monitorexit op bytecode-niveau.

Aanleiding voor ontstaan

In multithreadingtoepassingen zonder synchronisatie treedt race condition op — wanneer twee threads tegelijkertijd dezelfde gegevens wijzigen, leidt dit tot onvoorspelbare resultaten. Synchronized werd het eerste en belangrijkste hulpmiddel van Java om dit probleem te bestrijden, met een eenvoudige declaratieve syntaxis die voor elke ontwikkelaar toegankelijk is.

Hoe werkt synchronized?

Het mechanisme van synchronized is gebaseerd op het concept van een monitor — een hoogwaardig synchronisatieprimitief dat in elk Java-object is ingebouwd. De monitor wordt aan het object gekoppeld bij het eerste gebruik van een synchronized blok erop.

Objectmonitor

Elk object in Java heeft een bijbehorende monitor. Wanneer een thread een synchronized blok betreedt, neemt deze de monitor van het object over. Als de monitor al door een andere thread is bezet, wordt de thread geblokkeerd totdat deze vrijkomt. In bytecode komt dit overeen met het paar instructies monitorenter en monitorexit.

Vergrendelingsstatussen (biased locking)

De JVM optimaliseert synchronized via verschillende niveaus: biased locking (gekeurde vergrendeling) voor single-thread toegang, lightweight locking (lichte vergrendeling) bij lage concurrentie en heavyweight locking (zware vergrendeling) bij intense concurrentie met deelname van het besturingssysteem. Deze niveaus verhogen de prestaties zonder de code te wijzigen.

java
class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

De happens-before regel

Synchronized stelt de happens-before-relatie in: alle acties in een thread vóór het verlaten van een synchronized blok zijn zichtbaar voor een andere thread na het betreden van het blok dat op hetzelfde object is gesynchroniseerd. Dit garandeert niet alleen wederzijdse uitsluiting, maar ook de consistentie van gegevens voor alle threads.

Synchronized methode vs blok

Java biedt twee manieren om synchronized toe te passen: op methodeniveau en op blokniveau. De keuze tussen beide beïnvloedt de prestaties en granulariteit van de synchronisatie.

Synchronized methode

Door een methode te markeren met de modifier synchronized, synchroniseert u deze automatisch op de huidige instantie (voor een gewone methode) of op het Class-object (voor een statische methode). Dit is de eenvoudigste manier om wederzijdse uitsluiting te garanderen, maar is vaak overbodig als het kritieke gedeelte slechts een klein deel van de methode vormt en de rest van de code geen synchronisatie vereist.

Synchronized blok

Het synchronized blok biedt nauwkeurige controle: u geeft monitor-object op en synchroniseert alleen het benodigde codegedeelte, terwijl de rest van de methode buiten de vergrendeling blijft. Dit minimaliseert de tijd dat de monitor wordt vastgehouden en verhoogt de algehele prestaties van de toepassing in een multithreadingomgeving, omdat andere threads parallel niet-gerelateerde code kunnen uitvoeren zonder te wachten op het vrijkomen van de monitor.

java
class DataProcessor {
    private final Object lock = new Object();

    public void process() {
        // code buiten kritieke sectie - zonder synchronisatie
        prepareData()

        synchronized (lock) {
            // alleen dit blok is beschermd
            updateSharedState()
        }

        // verder zonder vergrendeling
        cleanup()
    }
}
CriteriumSynchronized methodeSynchronized blok
Monitorthis (instantie) of Classelk willekeurig object
Granulariteitgehele methodealleen benodigde code
Leesbaarheidhooggemiddeld
Prestatieslager bij grote methodehoger bij kleine kritieke sectie

Synchronized in Android

In Android-ontwikkeling wordt synchronized veel gebruikt voor de bescherming van SharedPreferences, databasetoegang en UI-componenten. Het gebruik ervan op de hoofdthread wordt echter ten strengste afgeraden vanwege het risico op vastlopen van de interface.

Gebruik met SharedPreferences

SharedPreferences in Android biedt basis-threadveiligheid, maar bij bewerking door meerdere threads via Editor kan externe synchronisatie nodig zijn. Een synchronized blok met een apart vergrendelingsobject garandeert de consistentie van wijzigingen.

kotlin
class PreferencesManager(private val prefs: SharedPreferences) {
    private val lock = Any()

    fun writeToken(token: String) {
        synchronized (lock) {
            prefs.edit()
                .putString("auth_token", token)
                .apply()
        }
    }
}

Beperkingen in Android-toepassingen

De belangrijkste beperking van synchronized op Android — threadblokkering. In tegenstelling tot coroutines met Mutex, blokkeert synchronized de volledige systeemthread. Op de hoofdthread veroorzaakt dit ANR. In moderne Android-ontwikkeling wordt aanbevolen synchronized te vervangen door coroutines (suspend Mutex) of atomaire typen (AtomicInteger).

Alternatieven voor synchronized

Modern Java en Kotlin bieden verschillende alternatieven voor synchronized, die elk dezelfde taken oplossen met minder beperkingen of betere prestaties.

Lock uit java.util.concurrent

De interface Lock met implementaties ReentrantLock en ReadWriteLock biedt time-outs, onderbreekbaar wachten en meerdere Condition-wachtrijen. Het is flexibeler dan synchronized, maar vereist expliciete vrijgave in finally, wat het risico op fouten bij een vergeten unlock vergroot.

Atomaire klassen

De klassen AtomicInteger, AtomicLong, AtomicReference en andere gebruiken Lock-Free algoritmen op basis van CAS (Compare-And-Swap). Ze zijn aanzienlijk sneller dan synchronized in scenario's met matige concurrentie, omdat ze threads niet blokkeren, maar optimistische herhaalde pogingen uitvoeren en geen contextomschakeling door de OS-kernel vereisen.

ThreadLocal en threadveiligheid

ThreadLocal biedt een alternatieve benadering: elke ThreadLocal-variabele is geïsoleerd binnen één thread en vereist geen synchronisatie voor lezen en schrijven. Dit elimineert volledig de noodzaak voor synchronized voor gegevens die niet tussen threads moeten worden gedeeld. ThreadLocal wordt actief gebruikt in frameworks (Spring, Hibernate) voor het opslaan van transactiecontext en sessies.

Coroutines en compose-benadering

In Kotlin-projecten voor Android is het alternatief voor synchronized Mutex uit kotlinx.coroutines. Het blokkeert de besturingssysteemthread niet, maar onderbreekt de coroutine tot het vrijgeven van de vergrendeling — dit maakt efficiënt gebruik van poolthreads mogelijk en voorkomt ANR bij lang wachten op het vrijkomen van een bron.

kotlin
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

val mutex = Mutex()
var counter = 0

suspend fun safeIncrement() {
    mutex.withLock {
        counter++
    }
}

Prestaties van synchronized

De prestaties van synchronized zijn aanzienlijk veranderd in de recente versies van Java. Vroeger werd het beschouwd als een „zwaar„ mechanisme, maar moderne JVM's hebben de meeste overhead geëlimineerd dankzij geavanceerde optimalisaties van de JIT-compiler. Laten we in detail bekijken hoe de virtuele machine gesynchroniseerde code tijdens runtime versnelt.

Biased Locking en Lock Coarsening

De JIT-compiler van de JVM past verschillende optimalisaties toe: biased locking elimineert synchronisatie als de vergrendeling altijd door één thread wordt overgenomen; lock coarsening voegt aangrenzende synchronized blokken samen tot één; lock elimination verwijdert synchronisatie als het object slechts voor één thread toegankelijk is. Deze optimalisaties maken synchronized praktisch gratis bij lage concurrentie.

Concurrentiemeting en optimalisatiekeuze

De JVM bepaalt het concurrentieniveau voor elk object: bij afwezigheid van concurrentie wordt biased locking ingeschakeld, bij het verschijnen van een tweede thread gaat de vergrendeling over in de lightweight-modus met spin-waiting, en pas bij lang wachten — in heavyweight met systeem-mutex. Deze escalatie vindt automatisch plaats en de ontwikkelaar hoeft niet handmatig een strategie te kiezen.

Vergelijking met Lock en atomaire klassen

In moderne benchmarks (Java 17+) vertoont synchronized prestaties vergelijkbaar met ReentrantLock bij lage en matige concurrentie. Bij hoge concurrentie kan Lock een voordeel hebben dankzij een efficiëntere wachtrij met ondersteuning voor time-outs en onderbrekingen. Voor systemen met hoge belasting waar concurrentie constant is, biedt ReentrantLock in fair-modus voorspelbaarder gedrag.

Atomaire klassen (AtomicInteger, AtomicReference) blijven het snelst voor eenvoudige tellers en vlaggen dankzij Lock-Free implementatie op CAS. Ze blokkeren threads helemaal niet — bij een conflict wordt de bewerking eenvoudig in een lus herhaald. Dit geeft een prestatieverbetering van 3-5 keer in vergelijking met synchronized bij tellerophogingen op 4-8 threads.

Veelgestelde vragen

Wat is het verschil tussen synchronized en volatile?

Synchronized biedt zowel wederzijdse uitsluiting als zichtbaarheid. Volatile garandeert alleen de zichtbaarheid van wijzigingen — schrijven naar een volatile-variabele is zichtbaar voor alle threads, maar voorkomt niet gelijktijdige wijziging, dat wil zeggen, het beschermt niet tegen race conditions.

Kan synchronized deadlock veroorzaken?

Ja, deadlock is mogelijk bij geneste synchronisatie met verschillende volgorde van monitoren. Bijvoorbeeld, de ene thread roept synchronized(a) { synchronized(b) } aan en de andere — synchronized(b) { synchronized(a) }. Vermijd geneste synchronized blokken of bepaal een vaste volgorde van monitoren.

Wat is een monitor in Java?

Een monitor is een synchronisatiemechanisme dat aan elk Java-object is gekoppeld. Het garandeert dat slechts één thread synchronized code op dat object uitvoert. De monitor omvat de vergrendeling, een wachtrij en een pool van threads die wachten op melding via wait/notify.

Is Lock sneller dan synchronized?

In moderne versies van Java (17+) staat synchronized niet achter bij Lock qua prestaties dankzij JIT-optimalisaties (biased locking, lock coarsening). Lock heeft de voorkeur niet vanwege snelheid, maar vanwege extra mogelijkheden: time-outs, onderbreekbaar wachten en meerdere Condition.

Hoe werkt synchronized met statische methoden?

Een statische synchronized methode gebruikt de monitor van het Class-object van die klasse, niet van de instantie. Dit betekent dat de synchronisatie alle instanties van de klasse omvat. Niet-statische en statische synchronized methoden gebruiken verschillende monitoren en blokkeren elkaar niet.

Samenvatting

  • Synchronized — ingebouwd Java-synchronisatiemechanisme op basis van monitoren.
  • Objectmonitor — interne JVM-structuur die wederzijdse uitsluiting waarborgt.
  • Methoden wait/notify worden alleen gebruikt binnen synchronized blokken of methoden.
  • Synchronized blok heeft de voorkeur boven een methode vanwege fijnere synchronisatiegranulariteit.
  • Happens-before garandeert zichtbaarheid van wijzigingen tussen threads bij synchronisatie op hetzelfde object.
  • Deadlock — het grootste risico bij geneste synchronisatie met verschillende monitorvolgorde.
  • Alternatieven — Lock, atomaire klassen en coroutines met suspending Mutex.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook