Synchronized: vad är det, funktionsprincip och användning i Java

Författare: IT Sectr Publicerad: 2026-03-19 Lästid: 8 min

Synchronized är en inbyggd synkroniseringsmekanism i programmeringsspråket Java som ger exklusiv åtkomst till kritiska avsnitt av koden. Enligt Oracle, 2024 garanterar modifieraren synchronized att endast en tråd kan exekvera den markerade metoden eller blocket vid en given tidpunkt. Denna mekanism är baserad på monitorer — ett fundamentalt koncept inom operativsystem som säkerställer korrekt funktion av flertrådade applikationer på alla komplexitetsnivåer.

Huvudpunkter

  • Synchronized — Java-nyckelord för trådsäker åtkomst till data.
  • Objektmonitor — den interna mekanism som synkronisering bygger på.
  • Synchronized metod låser hela metoden på instans- eller klassnivå.
  • Synchronized block tillåter synkronisering av endast en del av koden.
  • Deadlock — ett av huvudproblemen vid nästlad synkronisering.

Vad är synchronized?

Synchronized är ett nyckelord i Java som garanterar att endast en tråd åt gången exekverar den skyddade koddelen, vilket förhindrar dataskador vid parallell åtkomst. Det dök upp i första versionen av Java och förblir det enklaste sättet att säkerställa trådsäkerhet för utvecklare på alla nivåer.

Definition och roll i Java

Modifieraren synchronized löser två uppgifter: ömsesidig uteslutning (mutual exclusion) och synlighet av ändringar (visibility). När en tråd lämnar ett synchronized block blir alla ändringar garanterat synliga för andra trådar som går in i blocket som synkroniserats på samma objekt.

Synchronized kan tillämpas på hela metoden eller på ett godtyckligt kodblock med angivande av monitorobjektet. I båda fallen infogar JVM instruktionerna monitorenter och monitorexit på bytekodnivå.

Bakgrund till uppkomsten

I flertrådade applikationer utan synkronisering uppstår race condition — när två trådar samtidigt ändrar samma data, vilket leder till oförutsägbara resultat. Synchronized blev det första och främsta verktyget i Java för att bekämpa detta problem, med en enkel deklarativ syntax som är tillgänglig för alla utvecklare.

Hur fungerar synchronized?

Mekanismen för synchronized bygger på konceptet monitor — en högnivåsynkroniseringsprimitiv inbäddad i varje Java-objekt. Monitorn kopplas till objektet vid första användningen av ett synchronized block på det.

Objektmonitor

Varje objekt i Java har en associerad monitor. När en tråd går in i ett synchronized block tar den över objektets monitor. Om monitorn redan är upptagen av en annan tråd blockeras tråden tills den frigörs. I bytekod motsvaras detta av instruktionsparet monitorenter och monitorexit.

Låsningsstatus (biased locking)

JVM optimerar synchronized genom flera nivåer: biased locking (riktad låsning) för entrådad åtkomst, lightweight locking (lätt låsning) vid låg konkurrens och heavyweight locking (tung låsning) vid intensiv konkurrens med OS-deltagande. Dessa nivåer ökar prestanda utan att ändra koden.

java
class Counter {
    private int count = 0;

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

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

Happens-before-regeln

Synchronized etablerar relationen happens-before: alla åtgärder i en tråd före utträde ur ett synchronized block är synliga för en annan tråd efter inträde i blocket som synkroniserats på samma objekt. Detta garanterar inte bara ömsesidig uteslutning utan också datakonsistens för alla trådar.

Synchronized metod vs block

Java erbjuder två sätt att tillämpa synchronized: på metodnivå och på blocknivå. Valet mellan dem påverkar prestanda och granulariteten av synkroniseringen.

Synchronized metod

Genom att markera en metod med modifieraren synchronized synkroniserar du den automatiskt på den aktuella instansen (för en vanlig metod) eller på Class-objektet (för en statisk metod). Detta är det enklaste sättet att säkerställa ömsesidig uteslutning, men är ofta överflödigt om det kritiska avsnittet endast utgör en liten del av metoden och resten av koden inte kräver synkronisering.

Synchronized block

Synchronized block ger exakt kontroll: du anger monitorobjektet och synkroniserar endast den nödvändiga koddelen, medan resten av metoden förblir olåst. Detta minimerar tiden monitorn hålls och ökar applikationens övergripande prestanda i flertrådade miljöer, eftersom andra trådar kan exekvera orelaterad kod parallellt utan att vänta på att monitorn frigörs.

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

    public void process() {
        // kod utanför kritisk sektion - utan synkronisering
        prepareData()

        synchronized (lock) {
            // endast detta block är skyddat
            updateSharedState()
        }

        // fortsättning utan låsning
        cleanup()
    }
}
KriteriumSynchronized metodSynchronized block
Monitorthis (instans) eller Classvalfritt objekt
Granularitethela metodenendast nödvändig kod
Läsbarhethögmedel
Prestandalägre vid stor metodhögre vid liten kritisk sektion

Synchronized i Android

I Android-utveckling används synchronized i stor utsträckning för att skydda SharedPreferences, databastillgång och UI-komponenter. Dess användning på huvudtråden avråds dock starkt på grund av risken för att gränssnittet fryser.

Användning med SharedPreferences

SharedPreferences i Android ger grundläggande trådsäkerhet, men vid redigering av flera trådar via Editor kan extern synkronisering krävas. Ett synchronized block med ett separat låsobjekt garanterar ändringars konsistens.

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

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

Begränsningar i Android-applikationer

Den främsta begränsningen för synchronized på Android — trådblockering. Till skillnad från korutiner med Mutex blockerar synchronized hela systemtråden. På huvudtråden orsakar detta ANR. I modern Android-utveckling rekommenderas att ersätta synchronized med korutiner (suspend Mutex) eller atomära typer (AtomicInteger).

Alternativ till synchronized

Modern Java och Kotlin erbjuder flera alternativ till synchronized, som var och en löser samma uppgifter med färre begränsningar eller bättre prestanda.

Lock från java.util.concurrent

Gränssnittet Lock med implementeringarna ReentrantLock och ReadWriteLock erbjuder tidsgränser, avbrytbar väntan och flera Condition-köer. Det är mer flexibelt än synchronized men kräver explicit frigöring i finally, vilket ökar risken för fel vid glömd unlock.

Atomära klasser

Klasserna AtomicInteger, AtomicLong, AtomicReference och andra använder Lock-Free-algoritmer baserade på CAS (Compare-And-Swap). De är betydligt snabbare än synchronized i scenarier med måttlig konkurrens, eftersom de inte blockerar trådar utan utför optimistiska återförsök och kräver inte kontextväxling av OS-kärnan.

ThreadLocal och trådsäkerhet

ThreadLocal erbjuder ett alternativt tillvägagångssätt: varje ThreadLocal-variabel är isolerad inom ramen för en tråd och kräver ingen synkronisering för läsning och skrivning. Detta eliminerar helt behovet av synchronized för data som inte bör delas mellan trådar. ThreadLocal används aktivt i ramverk (Spring, Hibernate) för lagring av transaktionskontext och sessioner.

Korutiner och compose-metod

I Kotlin-projekt för Android är alternativet till synchronized Mutex från kotlinx.coroutines. Det blockerar inte operativsystemets tråd utan pausar korutinen tills låset frigörs — detta möjliggör effektiv användning av pooltrådar och undvikande av ANR vid lång väntan på resursfrigöring.

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

val mutex = Mutex()
var counter = 0

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

Prestanda för synchronized

Prestandan för synchronized har förändrats avsevärt i de senaste versionerna av Java. Tidigare ansågs det vara en "tung" mekanism, men moderna JVM:er har eliminerat de flesta overheadkostnaderna tack vare avancerade optimeringar av JIT-kompilatorn. Låt oss i detalj undersöka hur den virtuella maskinen accelererar synkroniserad kod vid körning.

Biased Locking och Lock Coarsening

JVM:ens JIT-kompilator tillämpar flera optimeringar: biased locking eliminerar synkronisering om låset alltid tas av en tråd; lock coarsening slår samman angränsande synchronized block till ett; lock elimination tar bort synkronisering om objektet endast är tillgängligt för en tråd. Dessa optimeringar gör synchronized praktiskt taget gratis vid låg konkurrens.

Konkurrensmätning och optimeringsval

JVM bestämmer konkurrensnivån för varje objekt: vid frånvaro av konkurrens aktiveras biased locking, när en andra tråd dyker upp övergår låset till lightweight-läge med spin-väntan, och först vid lång väntan — till heavyweight med systemmutex. Denna eskalering sker automatiskt och utvecklaren behöver inte manuellt välja strategi.

Jämförelse med Lock och atomära klasser

I moderna benchmarks (Java 17+) visar synchronized prestanda jämförbar med ReentrantLock vid låg och måttlig konkurrens. Vid hög konkurrens kan Lock ha en fördel tack vare en effektivare väntekö med stöd för tidsgränser och avbrott. För högbelastade system där konkurrensen är konstant ger ReentrantLock i fair-läge mer förutsägbart beteende.

Atomära klasser (AtomicInteger, AtomicReference) förblir snabbast för enkla räknare och flaggor tack vare Lock-Free-implementering på CAS. De blockerar inte trådar alls — vid konflikt upprepas operationen helt enkelt i en loop. Detta ger en prestandaökning på 3-5 gånger jämfört med synchronized vid räknarökningar på 4-8 trådar.

Vanliga frågor

Vad är skillnaden mellan synchronized och volatile?

Synchronized ger både ömsesidig uteslutning och synlighet. Volatile garanterar endast synlighet av ändringar — skrivning till en volatile-variabel är synlig för alla trådar, men förhindrar inte samtidig ändring, det vill säga skyddar inte mot race condition.

Kan synchronized orsaka deadlock?

Ja, deadlock är möjligt vid nästlad synkronisering med olika monitorordning. Till exempel anropar en tråd synchronized(a) { synchronized(b) }, och en annan — synchronized(b) { synchronized(a) }. Undvik nästlade synchronized block eller fastställ en enhetlig monitorordning.

Vad är en monitor i Java?

Monitor är en synkroniseringsmekanism associerad med varje Java-objekt. Den garanterar att endast en tråd exekverar synchronized kod på det objektet. Monitorn omfattar låset, väntekön och en pool av trådar som väntar på meddelande via wait/notify.

Är Lock snabbare än synchronized?

I moderna versioner av Java (17+) ligger synchronized inte efter Lock i prestanda tack vare JIT-optimeringar (biased locking, lock coarsening). Lock föredras inte på grund av hastighet utan på grund av extra funktioner: tidsgränser, avbrytbar väntan och flera Condition.

Hur fungerar synchronized med statiska metoder?

Statisk synchronized metod använder monitorn för klassens Class-objekt, inte instansens. Detta innebär att synkroniseringen omfattar alla instanser av klassen. Icke-statiska och statiska synchronized metoder använder olika monitorer och blockerar inte varandra.

Sammanfattning

  • Synchronized — inbyggd Java-synkroniseringsmekanism baserad på monitorer.
  • Objektmonitor — intern JVM-struktur som säkerställer ömsesidig uteslutning.
  • Metoderna wait/notify används endast inom synchronized block eller metoder.
  • Synchronized block är att föredra framför metod på grund av finare synkroniseringsgranularitet.
  • Happens-before garanterar synlighet av ändringar mellan trådar vid synkronisering på samma objekt.
  • Deadlock — huvudrisken vid nästlad synkronisering med olika monitorordning.
  • Alternativ — Lock, atomära klasser och korutiner med suspending Mutex.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också