Synchronized: co to je, princip činnosti a použití v Java

Autor: IT Sectr Publikováno: 2026-03-19 Doba čtení: 8 min

Synchronized je vestavěný synchronizační mechanismus v jazyce Java, který zajišťuje exkluzivní přístup ke kritickým sekcím kódu. Podle Oracle, 2024 modifikátor synchronized zaručuje, že pouze jedno vlákno může spouštět označenou metodu nebo blok v určitém okamžiku. Tento mechanismus je založen na monitorech — fundamentálním konceptu operačních systémů, který zajišťuje správnou činnost vícevláknových aplikací na všech úrovních složitosti.

Hlavní body

  • Synchronized — klíčové slovo Java pro bezpečný přístup k datům.
  • Monitor objektu — vnitřní mechanismus, na kterém je založena synchronizace.
  • Synchronized metoda blokuje celou metodu na úrovni instance nebo třídy.
  • Synchronized blok umožňuje synchronizovat pouze část kódu.
  • Deadlock — jeden z hlavních problémů při vnořené synchronizaci.

Co je synchronized?

Synchronized je klíčové slovo v Java, které zaručuje, že pouze jedno vlákno současně spouští chráněnou část kódu, čímž zabraňuje poškození dat při paralelním přístupu. Objevilo se v první verzi Java a zůstává nejjednodušším způsobem zajištění bezpečnosti vláken pro vývojáře všech úrovní.

Definice a role v Java

Modifikátor synchronized řeší dva úkoly: vzájemné vyloučení (mutual exclusion) a viditelnost změn (visibility). Když vlákno opustí synchronized blok, všechny změny jsou zaručeně viditelné pro další vlákna vstupující do bloku synchronizovaného na stejném objektu.

Synchronized lze aplikovat na celou metodu nebo na libovolný blok kódu s určením monitorovacího objektu. V obou případech JVM vkládá instrukce monitorenter a monitorexit na úrovni bytekódu.

Důvody vzniku

Ve vícevláknových aplikacích bez synchronizace vzniká závitové prohledávání (race condition) — když dvě vlákna současně mění stejná data, což vede k nepředvídatelným výsledkům. Synchronized se stal prvním a hlavním nástrojem Java pro boj s tímto problémem, poskytující jednoduchou deklarativní syntaxi přístupnou každému vývojáři.

Jak synchronized funguje?

Mechanismus synchronized je založen na konceptu monitoru — vysokoúrovňového synchronizačního primitivu vestavěného do každého objektu Java. Monitor je k objektu připojen při prvním použití synchronized bloku na něm.

Monitor objektu

Každý objekt v Java má přidružený monitor. Když vlákno vstoupí do synchronized bloku, převezme monitor objektu. Pokud je monitor již obsazen jiným vláknem, vlákno je blokováno do uvolnění. V bytekódu tomu odpovídá dvojice instrukcí monitorenter a monitorexit.

Stavy zámku (biased locking)

JVM optimalizuje synchronized prostřednictvím několika úrovní: biased locking (předpojaté zamykání) pro jednovláknový přístup, lightweight locking (lehlé zamykání) při nízké konkurenci a heavyweight locking (těžké zamykání) při intenzivní konkurenci s účastí OS. Tyto úrovně zvyšují výkon bez změny kódu.

java
class Counter {
    private int count = 0;

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

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

Pravidlo happens-before

Synchronized vytváří vztah happens-before: všechny akce ve vlákně před opuštěním synchronized bloku jsou viditelné pro jiné vlákno po vstupu do bloku synchronizovaného na stejném objektu. To zaručuje nejen vzájemné vyloučení, ale také konzistenci dat pro všechna vlákna.

Synchronized metoda vs blok

Java nabízí dva způsoby aplikace synchronized: na úrovni metody a na úrovni bloku. Volba mezi nimi ovlivňuje výkon a granularitu synchronizace.

Synchronized metoda

Označením metody modifikátorem synchronized ji automaticky synchronizujete na aktuální instanci (pro běžnou metodu) nebo na objektu Class (pro statickou metodu). To je nejjednodušší způsob zajištění vzájemného vyloučení, ale často je nadbytečný, pokud kritická sekce tvoří pouze malou část metody a zbytek kódu nevyžaduje synchronizaci.

Synchronized blok

Synchronized blok poskytuje přesnou kontrolu: určíte monitorovací objekt a synchronizujete pouze potřebnou část kódu, přičemž zbytek metody zůstává mimo zámek. To minimalizuje dobu držení monitoru a zvyšuje celkový výkon aplikace ve vícevláknovém prostředí, protože ostatní vlákna mohou paralelně spouštět nesouvisející kód bez čekání na uvolnění monitoru.

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

    public void process() {
        // kód mimo kritickou sekci - bez synchronizace
        prepareData()

        synchronized (lock) {
            // pouze tento blok je chráněn
            updateSharedState()
        }

        // pokračování bez zámku
        cleanup()
    }
}
KritériumSynchronized metodaSynchronized blok
Monitorthis (instance) nebo Classlibovolný objekt
Granularitacelá metodapouze potřebný kód
Čitelnostvysokástřední
Výkonnižší u velké metodyvyšší u malé kritické sekce

Synchronized v Android

Při vývoji pro Android se synchronized široce používá k ochraně SharedPreferences, přístupu k databázi a komponent UI. Jeho použití na hlavním vlákně se však kategoricky nedoporučuje kvůli riziku zamrznutí rozhraní.

Použití s SharedPreferences

SharedPreferences v Android poskytuje základní bezpečnost vláken, ale při úpravě více vlákny přes Editor může být vyžadována externí synchronizace. Synchronized blok s odděleným objektem zámku zaručuje konzistenci změn.

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

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

Omezení v aplikacích pro Android

Hlavní omezení synchronized na Android — blokování vlákna. Na rozdíl od coroutin s Mutex, synchronized blokuje celé systémové vlákno. Na hlavním vlákně to způsobuje ANR. V moderním vývoji pro Android se doporučuje nahradit synchronized coroutinami (suspend Mutex) nebo atomickými typy (AtomicInteger).

Alternativy k synchronized

Moderní Java a Kotlin nabízejí několik alternativ k synchronized, z nichž každá řeší stejné úkoly s menším počtem omezení nebo lepším výkonem.

Lock z java.util.concurrent

Rozhraní Lock s implementacemi ReentrantLock a ReadWriteLock poskytuje časové limity, přerušitelné čekání a několik front Condition. Je flexibilnější než synchronized, ale vyžaduje explicitní uvolnění v finally, což zvyšuje riziko chyby při zapomenutém unlock.

Atomické třídy

Třídy AtomicInteger, AtomicLong, AtomicReference a další používají Lock-Free algoritmy založené na CAS (Compare-And-Swap). Jsou výrazně rychlejší než synchronized ve scénářích s mírnou konkurencí, protože neblokují vlákna, ale provádějí optimistické opakované pokusy a nevyžadují přepínání kontextu jádrem OS.

ThreadLocal a bezpečnost vláken

ThreadLocal poskytuje alternativní přístup: každá proměnná ThreadLocal je izolována v rámci jednoho vlákna a nevyžaduje synchronizaci pro čtení a zápis. To zcela eliminuje potřebu synchronized pro data, která by neměla být sdílena mezi vlákny. ThreadLocal je aktivně používán v rámcích (Spring, Hibernate) pro ukládání kontextu transakcí a relací.

Coroutiny a přístup compose

V Kotlin projektech pro Android je alternativou k synchronized Mutex z kotlinx.coroutines. Neblokuje vlákno operačního systému, ale pozastaví coroutinu do uvolnění zámku — to umožňuje efektivní využití vláken z poolu a vyhnutí se ANR při dlouhém čekání na uvolnění prostředku.

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

val mutex = Mutex()
var counter = 0

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

Výkon synchronized

Výkon synchronized se v posledních verzích Java výrazně změnil. Dříve byl považován za „těžký„ mechanismus, ale moderní JVM odstranily většinu režie díky pokročilým optimalizacím JIT kompilátoru. Pojďme se podrobně podívat, jak virtuální stroj urychluje synchronizovaný kód za běhu.

Biased Locking a Lock Coarsening

JIT kompilátor JVM aplikuje několik optimalizací: biased locking eliminuje synchronizaci, pokud zámek vždy přebírá jedno vlákno; lock coarsening spojuje sousední synchronized bloky do jednoho; lock elimination odstraňuje synchronizaci, pokud je objekt přístupný pouze jednomu vláknu. Tyto optimalizace činí synchronized prakticky bezplatným při nízké konkurenci.

Měření konkurence a výběr optimalizace

JVM určuje úroveň konkurence pro každý objekt: při nepřítomnosti konkurence se aktivuje biased locking, při objevení druhého vlákna přechází zámek do režimu lightweight se spin-čekáním a teprve při dlouhém čekání — do heavyweight se systémovým mutexem. Tato eskalace probíhá automaticky a vývojář nemusí ručně vybírat strategii.

Srovnání s Lock a atomickými třídami

V moderních benchmarkách (Java 17+) vykazuje synchronized výkon srovnatelný s ReentrantLock při nízké a střední konkurenci. Při vysoké konkurenci může mít Lock výhodu díky efektivnější frontě čekání s podporou timeoutů a přerušení. Pro vysoce zatížené systémy, kde je konkurence konstantní, poskytuje ReentrantLock v režimu fair předvídatelnější chování.

Atomické třídy (AtomicInteger, AtomicReference) zůstávají nejrychlejší pro jednoduché čítače a příznaky díky Lock-Free implementaci na CAS. Vůbec neblokují vlákna — při konfliktu se operace jednoduše opakuje ve smyčce. To poskytuje 3-5násobné zvýšení výkonu ve srovnání se synchronized u operací inkrementace čítače na 4-8 vláknech.

Často kladené otázky

Jaký je rozdíl mezi synchronized a volatile?

Synchronized poskytuje jak vzájemné vyloučení, tak viditelnost. Volatile zaručuje pouze viditelnost změn — zápis do volatile proměnné je viditelný pro všechna vlákna, ale nebrání současné změně, tedy nechrání před závitovým prohledáváním.

Může synchronized způsobit deadlock?

Ano, deadlock je možný při vnořené synchronizaci s různým pořadím monitorů. Například jedno vlákno volá synchronized(a) { synchronized(b) }, a druhé — synchronized(b) { synchronized(a) }. Vyhněte se vnořeným synchronized blokům nebo stanovte jednotné pořadí monitorů.

Co je monitor v Java?

Monitor je synchronizační mechanismus spojený s každým objektem Java. Zaručuje, že pouze jedno vlákno spouští synchronized kód na daném objektu. Monitor zahrnuje zámek, frontu čekání a sadu vláken čekajících na oznámení prostřednictvím wait/notify.

Je Lock rychlejší než synchronized?

V moderních verzích Java (17+) synchronized nezaostává za Lockem ve výkonu díky JIT optimalizacím (biased locking, lock coarsening). Lock je preferován ne kvůli rychlosti, ale kvůli dalším možnostem: časové limity, přerušitelné čekání a několik Condition.

Jak synchronized pracuje se statickými metodami?

Statická synchronized metoda používá monitor objektu Class dané třídy, nikoli instance. To znamená, že synchronizace se vztahuje na všechny instance třídy. Nestatické a statické synchronized metody používají různé monitory a vzájemně se neblokují.

Shrnutí

  • Synchronized — vestavěný synchronizační mechanismus Java založený na monitorech.
  • Monitor objektu — vnitřní struktura JVM zajišťující vzájemné vyloučení.
  • Metody wait/notify se používají pouze uvnitř synchronized bloků nebo metod.
  • Synchronized blok je preferován před metodou díky jemnější granularitě synchronizace.
  • Happens-before zaručuje viditelnost změn mezi vlákny při synchronizaci na stejném objektu.
  • Deadlock — hlavní riziko při vnořené synchronizaci s různým pořadím monitorů.
  • Alternativy — Lock, atomické třídy a coroutiny se suspending Mutex.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také