Synchronized: nedir, çalışma prensibi ve Java'da kullanımı

Yazar: IT Sectr Yayınlanma: 2026-03-19 Okuma süresi: 8 dk

Synchronized, Java dilinde yerleşik bir senkronizasyon mekanizmasıdır ve kritik kod bölümlerine özel erişim sağlar. Oracle, 2024'e göre, synchronized değiştiricisi, işaretlenen metot veya bloğun belirli bir zamanda yalnızca bir iş parçacığı tarafından yürütülebilmesini garanti eder. Bu mekanizma, işletim sistemlerinin temel bir kavramı olan monitörlere dayanır ve her karmaşıklık seviyesindeki çok iş parçacıklı uygulamaların doğru çalışmasını sağlar.

Önemli Noktalar

  • Synchronized — iş parçacığı güvenli veri erişimi için Java anahtar kelimesi.
  • Nesne monitörü — senkronizasyonun dayandığı iç mekanizma.
  • Synchronized metot tüm metodu örnek veya sınıf düzeyinde kilitler.
  • Synchronized blok kodun yalnızca bir bölümünü senkronize etmeye izin verir.
  • Deadlock — iç içe senkronizasyondaki ana sorunlardan biri.

Synchronized nedir?

Synchronized, Java'da aynı anda yalnızca bir iş parçacığının korunan bir kod bölümünü yürütmesini garanti eden ve eşzamanlı erişim sırasında veri bozulmasını önleyen bir anahtar kelimedir. Java'nın ilk sürümünde ortaya çıkmıştır ve her seviyedeki geliştirici için iş parçacığı güvenliği sağlamanın en basit yolu olmaya devam etmektedir.

Java'da tanımı ve rolü

synchronized değiştiricisi iki görevi çözer: karşılıklı dışlama (mutual exclusion) ve değişikliklerin görünürlüğü (visibility). Bir iş parçacığı synchronized bloktan çıktığında, tüm değişiklikler aynı nesne üzerinde senkronize edilmiş bir bloğa giren diğer iş parçacıklarına görünür olur.

Synchronized, bir metodun tamamına veya bir monitör nesnesi belirterek rastgele bir kod bloğuna uygulanabilir. Her iki durumda da JVM, bayt kodu düzeyinde monitorenter ve monitorexit talimatlarını ekler.

Ortaya çıkış nedenleri

Senkronizasyon olmadan çok iş parçacıklı uygulamalarda, iki iş parçacığı aynı anda aynı veriyi değiştirdiğinde yarış durumu (race condition) oluşur ve öngörülemeyen sonuçlara yol açar. Synchronized, bu sorunla mücadele etmek için Java'nın ilk ve ana aracı haline gelmiş, her geliştiricinin erişebileceği basit bir bildirim sözdizimi sağlamıştır.

Synchronized nasıl çalışır?

Synchronized mekanizması, her Java nesnesine yerleşik yüksek seviyeli bir senkronizyon ilkel öğesi olan monitör kavramına dayanır. Monitör, üzerinde ilk kez synchronized blok kullanıldığında bir nesneyle ilişkilendirilir.

Nesne monitörü

Java'daki her nesnenin ilişkili bir monitörü vardır. Bir iş parçacığı synchronized bloğa girdiğinde, nesnenin monitörünü alır. Monitör zaten başka bir iş parçacığı tarafından tutuluyorsa, iş parçacığı serbest kalana kadar bloke olur. Bayt kodunda bu, monitorenter ve monitorexit talimat çiftine karşılık gelir.

Kilit durumları (biased locking)

JVM, synchronized'ı birkaç seviyede optimize eder: tek iş parçacıklı erişim için biased locking (yanlı kilitleme), düşük rekabet için lightweight locking (hafif kilitleme) ve işletim sistemi katılımıyla yoğun rekabet için heavyweight locking (ağır kilitleme). Bu seviyeler, kodu değiştirmeden performansı artırır.

java
class Counter {
    private int count = 0;

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

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

Happens-before kuralı

Synchronized bir happens-before ilişkisi kurar: synchronized bloktan çıkmadan önce bir iş parçacığındaki tüm eylemler, aynı nesne üzerinde senkronize edilmiş bir bloğa girdikten sonra başka bir iş parçacığına görünür olur. Bu, yalnızca karşılıklı dışlamayı değil, tüm iş parçacıkları için veri tutarlılığını da garanti eder.

Synchronized metot vs blok

Java, synchronized'ı uygulamak için iki yol sunar: metot düzeyinde ve blok düzeyinde. Aralarındaki seçim, performansı ve senkronizasyon ayrıntı düzeyini etkiler.

Synchronized metot

Bir metodu synchronized değiştiricisiyle işaretlemek, onu otomatik olarak geçerli örnek (örnek metotları için) veya Class nesnesi (statik metotlar için) üzerinde senkronize eder. Bu, karşılıklı dışlamayı sağlamanın en basit yoludur, ancak kritik bölüm metodun yalnızca küçük bir parçasını oluşturuyorsa ve kodun geri kalanı senkronizasyon gerektirmiyorsa genellikle aşırıdır.

Synchronized blok

Synchronized blok hassas kontrol sağlar: monitör nesnesini belirtir ve kodun yalnızca gerekli bölümünü senkronize eder, metodun geri kalanını kilidin dışında bırakır. Bu, monitör tutma süresini en aza indirir ve çok iş parçacıklı bir ortamda uygulamanın genel performansını artırır, çünkü diğer iş parçacıkları monitörün serbest kalmasını beklemeden ilgisiz kodu paralel olarak yürütebilir.

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

    public void process() {
        // kritik bölüm dışındaki kod - senkronizasyon olmadan
        prepareData()

        synchronized (lock) {
            // yalnızca bu blok korunuyor
            updateSharedState()
        }

        // kilit olmadan devam
        cleanup()
    }
}
KriterSynchronized metotSynchronized blok
Monitörthis (örnek) veya Classherhangi bir nesne
Ayrıntı düzeyitüm metotyalnızca gerekli kod
Okunabilirlikyüksekorta
Performansbüyük metotlarda düşükküçük kritik bölümlerde yüksek

Android'de Synchronized

Android geliştirmede, synchronized SharedPreferences, veritabanı erişimi ve UI bileşenlerini korumak için yaygın olarak kullanılır. Ancak, arayüz donması riski nedeniyle ana iş parçacığında kullanımı kesinlikle önerilmez.

SharedPreferences ile kullanım

Android'de SharedPreferences temel iş parçacığı güvenliği sağlar, ancak Editor aracılığıyla birden çok iş parçacığından düzenleme yaparken harici senkronizasyon gerekebilir. Ayrı bir kilit nesnesiyle synchronized blok, değişikliklerin tutarlılığını garanti eder.

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 uygulamalarındaki sınırlamalar

Android'de synchronized'ın ana sınırlaması iş parçacığı bloklamasıdır. Mutex ile coroutine'lerin aksine, synchronized sistem iş parçacığını tamamen bloke eder. Ana iş parçacığında bu, ANR'ye neden olur. Modern Android geliştirmede, synchronized'ın coroutine'ler (suspend Mutex) veya atomik türler (AtomicInteger) ile değiştirilmesi önerilir.

Synchronized alternatifleri

Modern Java ve Kotlin, synchronized'a çeşitli alternatifler sunar; her biri aynı sorunları daha az sınırlama veya daha iyi performansla çözer.

java.util.concurrent'den Lock

Lock arayüzü, ReentrantLock ve ReadWriteLock uygulamalarıyla zaman aşımları, kesilebilir bekleme ve birden çok Condition kuyruğu sağlar. Synchronized'dan daha esnektir ancak finally içinde açıkça serbest bırakılması gerekir, bu da unlock unutulursa hata riskini artırır.

Atomik sınıflar

AtomicInteger, AtomicLong, AtomicReference ve diğer sınıflar, CAS'a (Compare-And-Swap) dayalı Lock-Free algoritmaları kullanır. Orta düzey rekabet senaryolarında synchronized'dan önemli ölçüde daha hızlıdırlar çünkü iş parçacıklarını bloke etmezler, işletim sistemi çekirdek bağlam değişimi gerektirmeden iyimser yeniden denemeler yaparlar.

ThreadLocal ve iş parçacığı güvenliği

ThreadLocal alternatif bir yaklaşım sunar: her ThreadLocal değişkeni tek bir iş parçacığı içinde yalıtılmıştır ve okuma ve yazma için senkronizasyon gerektirmez. Bu, iş parçacıkları arasında paylaşılmaması gereken veriler için synchronized ihtiyacını tamamen ortadan kaldırır. ThreadLocal, framework'lerde (Spring, Hibernate) işlem bağlamı ve oturumları depolamak için aktif olarak kullanılır.

Coroutine'ler ve compose yaklaşımı

Android için Kotlin projelerinde, synchronized'a bir alternatif kotlinx.coroutines'den Mutex'tir. İşletim sistemi iş parçacığını bloke etmez, kilidin serbest kalmasına kadar coroutine'i askıya alır — bu, havuz iş parçacıklarının verimli kullanılmasını ve kaynak serbest bırakılması için uzun beklemeler sırasında ANR'yi önler.

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

val mutex = Mutex()
var counter = 0

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

Synchronized performansı

Synchronized'ın performansı son Java sürümlerinde önemli ölçüde değişmiştir. Eskiden “ağır” bir mekanizma olarak kabul edilirdi, ancak modern JVM'ler gelişmiş JIT derleyici optimizasyonları sayesinde ek yükün çoğunu ortadan kaldırmıştır. Sanal makinenin çalışma zamanında senkronize kodu nasıl hızlandırdığına ayrıntılı olarak bakalım.

Biased Locking ve Lock Coarsening

JVM JIT derleyicisi birkaç optimizasyon uygular: biased locking, kilit her zaman aynı iş parçacığı tarafından alınıyorsa senkronizasyonu ortadan kaldırır; lock coarsening, bitişik synchronized bloklarını birleştirir; lock elimination, nesneye yalnızca bir iş parçacığı erişebiliyorsa senkronizasyonu kaldırır. Bu optimizasyonlar, düşük rekabette synchronized'ı neredeyse ücretsiz hale getirir.

Rekabet ölçümü ve optimizasyon seçimi

JVM her nesne için rekabet seviyesini belirler: rekabet olmadığında biased locking etkinleştirilir; ikinci bir iş parçacığı göründüğünde, kilit spin-bekleme ile lightweight moduna geçer; ve yalnızca uzun süreli bekleme sırasında sistem mutex'i ile heavyweight'e yükselir. Bu yükselme otomatik olarak gerçekleşir ve geliştiricinin manuel olarak bir strateji seçmesi gerekmez.

Lock ve atomik sınıflarla karşılaştırma

Modern karşılaştırmalarda (Java 17+), synchronized düşük ve orta rekabette ReentrantLock ile karşılaştırılabilir performans gösterir. Yüksek rekabette Lock, zaman aşımı ve kesme desteğiyle daha verimli bir bekleme kuyruğu sayesinde avantaja sahip olabilir. Rekabetin sabit olduğu yüksek yük sistemlerinde, fair modlu ReentrantLock daha öngörülebilir davranış sağlar.

Atomik sınıflar (AtomicInteger, AtomicReference), CAS tabanlı Lock-Free uygulaması sayesinde basit sayaçlar ve bayraklar için en hızlı olmaya devam eder. İş parçacıklarını hiç bloke etmezler — çakışma durumunda, işlem basitçe bir döngüde yeniden dener. Bu, 4-8 iş parçacığıyla sayaç artırma işlemlerinde synchronized'a kıyasla 3-5 kat performans artışı sağlar.

Sıkça Sorulan Sorular

Synchronized ve volatile arasındaki fark nedir?

Synchronized hem karşılıklı dışlama hem de görünürlük sağlar. Volatile yalnızca değişikliklerin görünürlüğünü garanti eder — volatile bir değişkene yazmak tüm iş parçacıklarına görünür ancak eşzamanlı değişikliği engellemez, yani yarış durumuna karşı koruma sağlamaz.

Synchronized deadlock'a neden olabilir mi?

Evet, farklı monitör sırasıyla iç içe senkronizasyonda deadlock mümkündür. Örneğin, bir iş parçacığı synchronized(a) { synchronized(b) } çağırırken, diğeri synchronized(b) { synchronized(a) } çağırır. İç içe synchronized bloklardan kaçının veya tutarlı bir monitör sırası belirleyin.

Java'da monitör nedir?

Monitör, her Java nesnesiyle ilişkili bir senkronizasyon mekanizmasıdır. Bu nesne üzerinde yalnızca bir iş parçacığının synchronized kodu yürütmesini garanti eder. Monitör, bir kilit, bir bekleme kuyruğu ve wait/notify yoluyla bildirim bekleyen iş parçacıklarından oluşan bir havuz içerir.

Lock, synchronized'dan daha hızlı mı?

Modern Java sürümlerinde (17+), synchronized JIT optimizasyonları (biased locking, lock coarsening) sayesinde performansta Lock'tan geri kalmaz. Lock, hız için değil, zaman aşımı, kesilebilir bekleme ve birden çok Condition kuyruğu gibi ek yetenekler için tercih edilir.

Statik metotlarla synchronized nasıl çalışır?

Statik synchronized metot, örnek değil, verilen sınıfın Class nesnesinin monitörünü kullanır. Bu, senkronizasyonun sınıfın tüm örneklerine uygulandığı anlamına gelir. Statik olmayan ve statik synchronized metotlar farklı monitörler kullanır ve birbirlerini bloke etmezler.

Özet

  • Synchronized — monitörlere dayalı Java yerleşik senkronizasyon mekanizması.
  • Nesne monitörü — karşılıklı dışlamayı sağlayan JVM iç yapısı.
  • Wait/notify metotları yalnızca synchronized blok veya metotlar içinde kullanılır.
  • Synchronized blok daha ince senkronizasyon ayrıntı düzeyi nedeniyle metoda tercih edilir.
  • Happens-before aynı nesnede senkronizasyon yaparken iş parçacıkları arasında değişikliklerin görünürlüğünü garanti eder.
  • Deadlock — farklı monitör sırasıyla iç içe senkronizasyonun ana riski.
  • Alternatifler — Lock, atomik sınıflar ve suspending Mutex ile coroutine'ler.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun