Synchronized: шта је то, принцип рада и употреба у Java

Аутор: IT Sectr Објављено: 2026-03-19 Време читања: 8 мин

Synchronized је уграђени механизам синхронизације у језику Java, који обезбеђује ексклузивни приступ критичним секцијама кода. Према Oracle, 2024, модификатор synchronized гарантује да само једна нит може извршавати означену методу или блок у одређеном тренутку. Овај механизам се заснива на мониторима — фундаменталном концепту оперативних система, који обезбеђује коректно функционисање вишенитних апликација свих нивоа сложености.

Главно

  • Synchronized — кључна реч Java за безбедан приступ подацима.
  • Монитор објекта — унутрашњи механизам на коме се заснива синхронизација.
  • Synchronized метода блокира целу методу на нивоу инстанце или класе.
  • Synchronized блок омогућава синхронизацију само дела кода.
  • Deadlock — један од главних проблема код угњеждене синхронизације.

Шта је synchronized?

Synchronized је кључна реч у Java која гарантује да само једна нит истовремено извршава заштићени део кода, спречавајући оштећење података при паралелном приступу. Појавила се у првој верзији Java и остаје најједноставнији начин обезбеђивања безбедности нити за програмере свих нивоа.

Дефиниција и улога у Java

Модификатор synchronized решава два задатка: међусобно искључивање (mutual exclusion) и видљивост промена (visibility). Када нит напусти synchronized блок, све промене су гарантовано видљиве другим нитима које улазе у блок синхронизован на истом објекту.

Synchronized се може применити на целу методу или на произвољни блок кода са навођењем објекта-монитора. У оба случаја JVM убацује инструкције monitorenter и monitorexit на нивоу бајт-кода.

Разлози настанка

У вишенитним апликацијама без синхронизације настаје тркачко стање (race condition) — када две нити истовремено мењају исте податке, доводећи до непредвидивих резултата. Synchronized је постао први и главни алат Java за борбу против овог проблема, пружајући једноставну декларативну синтаксу доступну сваком програмеру.

Како ради synchronized?

Механизам synchronized се заснива на концепту монитора — високонивоског примитива синхронизације уграђеног у сваки Java објекат. Монитор се повезује са објектом при првом коришћењу synchronized блока на њему.

Монитор објекта

Сваки објекат у Java има повезани монитор. Када нит уђе у synchronized блок, она преузима монитор објекта. Ако је монитор већ заузет другом нити, нит се блокира до ослобађања. У бајт-коду овоме одговара пар инструкција monitorenter и monitorexit.

Стања закључавања (biased locking)

JVM оптимизује synchronized кроз неколико нивоа: biased locking (пристрасно закључавање) за једнонитни приступ, lightweight locking (лако закључавање) при слабој конкуренцији и heavyweight locking (тешко закључавање) при интензивној конкуренцији са учешћем ОС. Ови нивои повећавају перформансе без промене кода.

java
class Counter {
    private int count = 0;

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

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

Правило happens-before

Synchronized успоставља релацију happens-before: све радње у нити пре изласка из synchronized блока видљиве су другој нити након уласка у блок синхронизован на истом објекту. Ово гарантује не само међусобно искључивање, већ и конзистентност података за све нити.

Synchronized метода vs блок

Java нуди два начина примене synchronized: на нивоу методе и на нивоу блока. Избор између њих утиче на перформансе и грануларност синхронизације.

Synchronized метода

Обележавањем методе модификатором synchronized, аутоматски је синхронизујете на текућој инстанци (за обичну методу) или на објекту Class (за статичку методу). Ово је најједноставнији начин обезбеђивања међусобног искључивања, али је често претерано ако критична секција чини само мали део методе, а остатак кода не захтева синхронизацију.

Synchronized блок

Synchronized блок даје прецизну контролу: наводите објекат-монитор и синхронизујете само потребан део кода, остављајући остатак методе ван закључавања. Ово минимизира време држања монитора и повећава укупне перформансе апликације у вишенитном окружењу, јер друге нити могу паралелно извршавати неповезани код без чекања на ослобађање монитора.

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

    public void process() {
        // код ван критичне секције - без синхронизације
        prepareData()

        synchronized (lock) {
            // само овај блок је заштићен
            updateSharedState()
        }

        // наставак без закључавања
        cleanup()
    }
}
КритеријумSynchronized методаSynchronized блок
Мониторthis (инстанца) или Classбило који објекат
Грануларностцела методасамо потребан код
Читљивоствисокасредња
Перформансениже код велике методевише код мале критичне секције

Synchronized у Android

У развоју за Android, synchronized се широко користи за заштиту SharedPreferences, приступа бази података и UI компоненти. Међутим, његова употреба на главној нити се категорички не препоручује због ризика од замрзавања интерфејса.

Употреба са SharedPreferences

SharedPreferences у Android обезбеђује основну безбедност нити, али при уређивању од стране више нити преко Editor-а може бити потребна спољашња синхронизација. Synchronized блок са засебним објектом закључавања гарантује конзистентност промена.

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

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

Ограничења у Android апликацијама

Главно ограничење synchronized на Android — блокирање нити. За разлику од корутина са Mutex, synchronized блокира целу системску нит. На главној нити ово изазива ANR. У модерном Android развоју препоручује се замена synchronized корутинама (suspend Mutex) или атомским типовима (AtomicInteger).

Алтернативе за synchronized

Модерни Java и Kotlin нуде неколико алтернатива за synchronized, од којих свака решава исте задатке са мање ограничења или бољим перформансама.

Lock из java.util.concurrent

Интерфејс Lock са имплементацијама ReentrantLock и ReadWriteLock пружа тајмауте, прекидиво чекање и више Condition редова. Флексибилнији је од synchronized, али захтева експлицитно ослобађање у finally, што повећава ризик од грешке при заборављеном unlock.

Атомске класе

Класе AtomicInteger, AtomicLong, AtomicReference и друге користе Lock-Free алгоритме засноване на CAS (Compare-And-Swap). Оне су значајно брже од synchronized у сценаријима са умереном конкуренцијом, јер не блокирају нити, већ извршавају оптимистичке поновне покушаје и не захтевају пребацивање контекста од стране језгра ОС.

ThreadLocal и безбедност нити

ThreadLocal пружа алтернативни приступ: свака ThreadLocal променљива је изолована у оквиру једне нити и не захтева синхронизацију за читање и писање. Ово потпуно елиминише потребу за synchronized за податке који не треба да се деле између нити. ThreadLocal се активно користи у фрејмворцима (Spring, Hibernate) за чување контекста транзакција и сесија.

Корутине и compose приступ

У Kotlin пројектима за Android, алтернатива synchronized-у је Mutex из kotlinx.coroutines. Он не блокира нит оперативног система, већ суспендује корутину до тренутка ослобађања закључавања — ово омогућава ефикасно коришћење нити из pool-а и избегавање ANR-а при дугом чекању на ослобађање ресурса.

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

val mutex = Mutex()
var counter = 0

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

Перформансе synchronized

Перформансе synchronized су се значајно промениле у последњим верзијама Java. Раније се сматрао „тешким„ механизмом, али модерне JVM су елиминисале већину додатних оптерећења захваљујући напредним оптимизацијама JIT компајлера. Размотримо детаљно како виртуелна машина убрзава синхронизовани код у рантајму.

Biased Locking и Lock Coarsening

JIT компајлер JVM примењује неколико оптимизација: biased locking елиминише синхронизацију ако закључавање увек преузима једна нит; lock coarsening обједињује суседне synchronized блокове у један; lock elimination уклања синхронизацију ако је објекат доступан само једној нити. Ове оптимизације чине synchronized практично бесплатним при ниској конкуренцији.

Мерење конкуренције и избор оптимизације

JVM одређује ниво конкуренције за сваки објекат: при одсуству конкуренције укључује се biased locking, при појави друге нити закључавање прелази у lightweight режим са spin-чекањем, и тек при дугом чекању — у heavyweight са системским мутексом. Ова ескалација се дешава аутоматски и програмер не мора ручно да бира стратегију.

Поређење са Lock и атомским класама

У модерним бенчмарковима (Java 17+) synchronized показује перформансе упоредиве са ReentrantLock при ниској и умереној конкуренцији. При високој конкуренцији Lock може имати предност захваљујући ефикаснијем реду чекања са подршком за тајмауте и прекиде. За високооптерећене системе где је конкуренција константна, ReentrantLock у fair режиму даје предвидљивије понашање.

Атомске класе (AtomicInteger, AtomicReference) остају најбрже за једноставне бројаче и заставице захваљујући Lock-Free имплементацији на CAS. Оне уопште не блокирају нити — при конфликту операција се једноставно понавља у петљи. Ово даје повећање перформанси од 3-5 пута у поређењу са synchronized на операцијама инкремента бројача при 4-8 нити.

Често постављана питања

Која је разлика између synchronized и volatile?

Synchronized обезбеђује и међусобно искључивање и видљивост. Volatile гарантује само видљивост промена — упис у volatile променљиву видљив је свим нитима, али не спречава истовремену измену, односно не штити од тркачког стања.

Може ли synchronized изазвати deadlock?

Да, deadlock је могућ код угњеждене синхронизације са различитим редоследом монитора. На пример, једна нит позива synchronized(a) { synchronized(b) }, а друга — synchronized(b) { synchronized(a) }. Избегавајте угњеждене synchronized блокове или фиксирајте јединствени редослед монитора.

Шта је монитор у Java?

Монитор је механизам синхронизације повезан са сваким Java објектом. Он гарантује да само једна нит извршава synchronized код на датом објекту. Монитор укључује закључавање, ред чекања и скуп нити које чекају обавештење путем wait/notify.

Да ли је Lock бржи од synchronized?

У модерним верзијама Java (17+) synchronized не заостаје за Lock-ом у перформансама захваљујући JIT оптимизацијама (biased locking, lock coarsening). Lock се преферира не због брзине, већ због додатних могућности: тајмаути, прекидиво чекање и више Condition.

Како synchronized ради са статичким методама?

Статичка synchronized метода користи монитор објекта Class дате класе, а не инстанце. То значи да се синхронизација простире на све инстанце класе. Нестатичке и статичке synchronized методе користе различите мониторе и не блокирају једна другу.

Резиме

  • Synchronized — уграђени механизам синхронизације Java заснован на мониторима.
  • Монитор објекта — унутрашња структура JVM која обезбеђује међусобно искључивање.
  • Методе wait/notify се користе само унутар synchronized блокова или метода.
  • Synchronized блок је пожељнији од методе због финије грануларности синхронизације.
  • Happens-before гарантује видљивост промена између нити при синхронизацији на истом објекту.
  • Deadlock — главни ризик код угњеждене синхронизације са различитим редоследом монитора.
  • Алтернативе — Lock, атомске класе и корутине са suspending Mutex.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође