Synchronized: ano ito, prinsipyo ng paggana at paggamit sa Java

May-akda: IT Sectr Nai-publish: 2026-03-19 Oras ng pagbabasa: 8 min

Synchronized ay isang built-in na mekanismo ng pag-synchronize sa wikang Java na nagbibigay ng eksklusibong access sa mga kritikal na seksyon ng code. Ayon sa Oracle, 2024, ginagarantiyahan ng modifier na synchronized na isang thread lamang ang maaaring magpatupad ng minarkahang method o block sa isang tiyak na oras. Ang mekanismong ito ay batay sa mga monitor — isang pangunahing konsepto ng mga operating system na nagsisiguro ng tamang paggana ng mga multithread na aplikasyon sa lahat ng antas ng pagiging kumplikado.

Mga pangunahing punto

  • Synchronized — keyword ng Java para sa ligtas na pag-access sa data.
  • Monitor ng object — panloob na mekanismo na pinagbabatayan ng pag-synchronize.
  • Synchronized method ay nagla-lock ng buong method sa antas ng instance o klase.
  • Synchronized block ay nagbibigay-daan sa pag-synchronize ng bahagi lamang ng code.
  • Deadlock — isa sa mga pangunahing problema sa nested na pag-synchronize.

Ano ang synchronized?

Synchronized ay isang keyword sa Java na ginagarantiyahan na isang thread lamang sa isang pagkakataon ang nagpapatupad ng protektadong bahagi ng code, na pumipigil sa pagkasira ng data sa parallel na pag-access. Lumitaw ito sa unang bersyon ng Java at nananatiling pinakasimpleng paraan upang matiyak ang kaligtasan ng thread para sa mga developer sa lahat ng antas.

Kahulugan at papel sa Java

Ang modifier na synchronized ay lumulutas ng dalawang gawain: mutual exclusion at visibility ng mga pagbabago. Kapag umalis ang isang thread sa synchronized block, lahat ng pagbabago ay garantisadong makikita ng ibang mga thread na pumapasok sa block na naka-synchronize sa parehong object.

Maaaring ilapat ang synchronized sa buong method o sa anumang block ng code na may pagtukoy sa object-monitor. Sa parehong kaso, ang JVM ay naglalagay ng mga instruction na monitorenter at monitorexit sa antas ng bytecode.

Mga dahilan ng paglitaw

Sa mga multithread na aplikasyon na walang pag-synchronize, nangyayari ang race condition — kapag dalawang thread ang sabay na nagbabago ng parehong data, na humahantong sa hindi inaasahang mga resulta. Ang Synchronized ay naging una at pangunahing tool ng Java upang labanan ang problemang ito, na nagbibigay ng simpleng deklaratibong syntax na naa-access sa bawat developer.

Paano gumagana ang synchronized?

Ang mekanismo ng synchronized ay batay sa konsepto ng monitor — isang mataas na antas na primitibo ng pag-synchronize na naka-embed sa bawat Java object. Ang monitor ay iniuugnay sa object sa unang paggamit ng synchronized block dito.

Monitor ng object

Bawat object sa Java ay may kaugnay na monitor. Kapag pumasok ang isang thread sa synchronized block, kinukuha nito ang monitor ng object. Kung ang monitor ay okupado na ng ibang thread, ang thread ay haharang hanggang sa ito ay pakawalan. Sa bytecode, ito ay tumutugma sa pares ng mga instruction na monitorenter at monitorexit.

Mga estado ng pag-lock (biased locking)

Ino-optimize ng JVM ang synchronized sa pamamagitan ng ilang antas: biased locking para sa single-thread na access, lightweight locking para sa mababang kompetisyon, at heavyweight locking para sa matinding kompetisyon na may partisipasyon ng OS. Ang mga antas na ito ay nagpapataas ng pagganap nang hindi binabago ang code.

java
class Counter {
    private int count = 0;

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

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

Ang panuntunang happens-before

Ang Synchronized ay nagtatag ng relasyong happens-before: lahat ng aksyon sa isang thread bago umalis sa synchronized block ay makikita ng ibang thread pagkatapos pumasok sa block na naka-synchronize sa parehong object. Ito ay ginagarantiyahan hindi lamang ang mutual exclusion, kundi pati na rin ang consistency ng data para sa lahat ng thread.

Synchronized method vs block

Nag-aalok ang Java ng dalawang paraan upang ilapat ang synchronized: sa antas ng method at sa antas ng block. Ang pagpili sa pagitan nila ay nakakaapekto sa pagganap at granularity ng pag-synchronize.

Synchronized method

Sa pamamagitan ng pagmamarka ng method gamit ang modifier na synchronized, awtomatiko mo itong sini-synchronize sa kasalukuyang instance (para sa ordinaryong method) o sa object na Class (para sa static na method). Ito ang pinakasimpleng paraan upang matiyak ang mutual exclusion, ngunit kadalasan ay labis kung ang kritikal na seksyon ay bumubuo lamang ng maliit na bahagi ng method at ang natitirang code ay hindi nangangailangan ng pag-synchronize.

Synchronized block

Ang synchronized block ay nagbibigay ng tumpak na kontrol: tinutukoy mo ang object-monitor at sini-synchronize lamang ang kinakailangang bahagi ng code, na iniiwan ang natitirang method sa labas ng pag-lock. Ito ay nagpapaliit sa oras ng paghawak ng monitor at nagpapataas sa pangkalahatang pagganap ng aplikasyon sa multithread na kapaligiran, dahil ang ibang mga thread ay maaaring magpatupad ng hindi kaugnay na code nang parallel nang hindi naghihintay sa paglabas ng monitor.

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

    public void process() {
        // code sa labas ng kritikal na seksyon - walang synchronize
        prepareData()

        synchronized (lock) {
            // tanging ang block na ito ay protektado
            updateSharedState()
        }

        // pagpapatuloy nang walang lock
        cleanup()
    }
}
KriteryaSynchronized methodSynchronized block
Monitorthis (instance) o Classanumang object
Granularitybuong methodkinakailangang code lamang
Pagkabasamataaskatamtaman
Pagganapmas mababa para sa malaking methodmas mataas para sa maliit na kritikal na seksyon

Synchronized sa Android

Sa pag-develop ng Android, ang synchronized ay malawakang ginagamit para sa proteksyon ng SharedPreferences, access sa database, at mga component ng UI. Gayunpaman, ang paggamit nito sa main thread ay mahigpit na hindi inirerekomenda dahil sa panganib ng pag-freeze ng interface.

Paggamit sa SharedPreferences

Ang SharedPreferences sa Android ay nagbibigay ng pangunahing kaligtasan ng thread, ngunit kapag na-edit ng maraming thread sa pamamagitan ng Editor, maaaring kailanganin ang panlabas na pag-synchronize. Ang synchronized block na may hiwalay na locking object ay ginagarantiyahan ang consistency ng mga pagbabago.

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

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

Mga limitasyon sa Android aplikasyon

Ang pangunahing limitasyon ng synchronized sa Android — pag-block ng thread. Hindi tulad ng coroutine na may Mutex, ni-lock ng synchronized ang buong system thread. Sa main thread, ito ay nagdudulot ng ANR. Sa modernong pag-develop ng Android, inirerekomenda na palitan ang synchronized ng coroutine (suspend Mutex) o atomic na uri (AtomicInteger).

Mga alternatibo sa synchronized

Ang modernong Java at Kotlin ay nag-aalok ng ilang alternatibo sa synchronized, na bawat isa ay lumulutas ng parehong mga gawain na may mas kaunting limitasyon o mas mahusay na pagganap.

Lock mula sa java.util.concurrent

Ang interface na Lock na may mga implementasyong ReentrantLock at ReadWriteLock ay nagbibigay ng mga timeout, interruptible na paghihintay, at maraming Condition queue. Ito ay mas flexible kaysa synchronized, ngunit nangangailangan ng explicit na pag-release sa finally, na nagpapataas ng panganib ng error kapag nakalimutan ang unlock.

Mga atomic na klase

Ang mga klase na AtomicInteger, AtomicLong, AtomicReference at iba pa ay gumagamit ng Lock-Free algorithm batay sa CAS (Compare-And-Swap). Ang mga ito ay makabuluhang mas mabilis kaysa synchronized sa mga senaryo na may katamtamang kompetisyon, dahil hindi nila ni-lolock ang mga thread, kundi nagsasagawa ng optimistikong pagsubok muli at hindi nangangailangan ng context switching ng OS kernel.

ThreadLocal at kaligtasan ng thread

Ang ThreadLocal ay nagbibigay ng alternatibong approach: bawat variable ng ThreadLocal ay nakahiwalay sa loob ng isang thread at hindi nangangailangan ng pag-synchronize para sa pagbasa at pagsulat. Ito ay ganap na nag-aalis ng pangangailangan para sa synchronized para sa data na hindi dapat ibahagi sa pagitan ng mga thread. Ang ThreadLocal ay aktibong ginagamit sa mga framework (Spring, Hibernate) para sa pag-imbak ng konteksto ng transaksyon at session.

Coroutine at compose approach

Sa mga proyektong Kotlin para sa Android, ang alternatibo sa synchronized ay Mutex mula sa kotlinx.coroutines. Hindi nito ni-lolock ang thread ng operating system, kundi sinuspinde ang coroutine hanggang sa pag-release ng lock — ito ay nagbibigay-daan sa mahusay na paggamit ng pool threads at pag-iwas sa ANR kapag matagal na naghihintay para sa pag-release ng resource.

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

val mutex = Mutex()
var counter = 0

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

Pagganap ng synchronized

Ang pagganap ng synchronized ay nagbago nang malaki sa mga kamakailang bersyon ng Java. Dati ito ay itinuturing na isang "mabigat" na mekanismo, ngunit ang mga modernong JVM ay nag-alis ng karamihan sa overhead salamat sa mga advanced na optimization ng JIT compiler. Tingnan natin nang detalyado kung paano pinapabilis ng virtual machine ang naka-synchronize na code sa runtime.

Biased Locking at Lock Coarsening

Ang JIT compiler ng JVM ay naglalapat ng ilang optimization: biased locking ay nag-aalis ng pag-synchronize kung ang lock ay palaging kinukuha ng isang thread; lock coarsening ay pinagsasama ang mga katabing synchronized block sa isa; lock elimination ay nag-aalis ng pag-synchronize kung ang object ay accessible lamang ng isang thread. Ang mga optimization na ito ay gumagawa ng synchronized na praktikal na libre sa mababang kompetisyon.

Pagsukat ng kompetisyon at pagpili ng optimization

Tinutukoy ng JVM ang antas ng kompetisyon para sa bawat object: sa kawalan ng kompetisyon, ang biased locking ay isinaaktibo; sa paglitaw ng pangalawang thread, ang lock ay lumipat sa lightweight mode na may spin-waiting; at sa mahabang paghihintay lamang — sa heavyweight na may system mutex. Ang escalation na ito ay awtomatikong nangyayari at ang developer ay hindi kailangang manu-manong pumili ng estratehiya.

Paghahambing sa Lock at atomic na klase

Sa mga modernong benchmark (Java 17+) ang synchronized ay nagpapakita ng pagganap na maihahambing sa ReentrantLock sa mababa at katamtamang kompetisyon. Sa mataas na kompetisyon, ang Lock ay maaaring magkaroon ng kalamangan dahil sa mas mahusay na waiting queue na may suporta para sa mga timeout at interrupt. Para sa mga system na may mataas na load kung saan ang kompetisyon ay pare-pareho, ang ReentrantLock sa fair mode ay nagbibigay ng mas predictable na pag-uugali.

Ang mga atomic na klase (AtomicInteger, AtomicReference) ay nananatiling pinakamabilis para sa mga simpleng counter at flag salamat sa Lock-Free implementation sa CAS. Hindi nila ni-lolock ang mga thread — sa conflict, ang operasyon ay inuulit lamang sa isang loop. Ito ay nagbibigay ng pagtaas ng pagganap ng 3-5 beses kumpara sa synchronized sa mga operasyon ng pagtaas ng counter sa 4-8 thread.

Mga madalas itanong

Ano ang pagkakaiba ng synchronized at volatile?

Synchronized ay nagbibigay ng parehong mutual exclusion at visibility. Ang Volatile ay ginagarantiyahan lamang ang visibility ng mga pagbabago — ang pagsulat sa volatile variable ay nakikita ng lahat ng thread, ngunit hindi pumipigil sa sabay na pagbabago, ibig sabihin hindi ito nagpoprotekta laban sa race condition.

Maaari bang magdulot ng deadlock ang synchronized?

Oo, ang deadlock ay posible sa nested na pag-synchronize na may iba't ibang pagkakasunod-sunod ng mga monitor. Halimbawa, ang isang thread ay tumatawag ng synchronized(a) { synchronized(b) }, at ang isa naman ay — synchronized(b) { synchronized(a) }. Iwasan ang nested synchronized block o magtakda ng nakapirming pagkakasunod-sunod ng mga monitor.

Ano ang monitor sa Java?

Monitor ay isang mekanismo ng pag-synchronize na nauugnay sa bawat Java object. Ito ay ginagarantiyahan na isang thread lamang ang nagpapatupad ng synchronized code sa object na iyon. Ang monitor ay kinabibilangan ng lock, waiting queue, at pool ng mga thread na naghihintay ng notification sa pamamagitan ng wait/notify.

Mas mabilis ba ang Lock kaysa synchronized?

Sa mga modernong bersyon ng Java (17+) ang synchronized ay hindi nahuhuli sa Lock sa pagganap salamat sa JIT optimization (biased locking, lock coarsening). Ang Lock ay mas pinipili hindi dahil sa bilis, kundi dahil sa mga karagdagang kakayahan: timeout, interruptible na paghihintay, at maraming Condition.

Paano gumagana ang synchronized sa static na method?

Static synchronized method ay gumagamit ng monitor ng Class object ng klase na iyon, hindi ng instance. Nangangahulugan ito na ang pag-synchronize ay sumasaklaw sa lahat ng instance ng klase. Ang non-static at static synchronized method ay gumagamit ng iba't ibang monitor at hindi nagla-lock sa isa't isa.

Buod

  • Synchronized — built-in na mekanismo ng pag-synchronize ng Java batay sa mga monitor.
  • Monitor ng object — panloob na istruktura ng JVM na nagsisiguro ng mutual exclusion.
  • Mga method na wait/notify ay ginagamit lamang sa loob ng synchronized block o method.
  • Blok synchronized ay mas gusto kaysa method dahil sa mas pinong granularity ng pag-synchronize.
  • Happens-before ay ginagarantiyahan ang visibility ng mga pagbabago sa pagitan ng mga thread sa pag-synchronize sa parehong object.
  • Deadlock — pangunahing panganib sa nested na pag-synchronize na may iba't ibang pagkakasunod-sunod ng monitor.
  • Mga alternatibo — Lock, atomic na klase, at coroutine na may suspending Mutex.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din