Synchronized anahtar kelimesi bir method üzerinde kullanıldığında bu methodu çağıran nesne (this) üzerinde bir kilit oluşturur. Bu nedenle bu nesne üzerinde synchronized anahtar kelimesine sahip tüm methodlar bu kilidi paylaşır.
Synchronized anahtar kelimesi bir nesneyi(instance) kilitler. Bir nesnenin birden fazla synchronized methodu varsa, birden fazla thread aynı anda bu nesnenin synchronized methodlarına erişemezler. Bir thread bir synchronized method içindeyken diğer threadler diğer synchronized methodlara erişemezler. Eğer bir method synchronized değilse, nesnenin diğer synchronized methodlar tarafından kilitlenip kilitlenmediğine bakılmaksızın bu methoda erişilir.


Bir methodu synchronized etmek, methoda ait bir instance’ı kilitlemek demektir. Nesneye ait birden fazla instance var ise, synchronized methodlar burada instance’ların methodlara erişimlerini engelleyemezler. Öncelikle eşzamanlı erişim sağlanmak istenen nesne ile ilgili bir tane instance olmalı. Controller ya da Service sınıfları Spring container tarafından oluşturulan bean’lerdir. Bu sınıflar default olarak singleton scope içindedir. Yani spring container çalıştırıldıktan sonra bu sınıf için bir instance oluşturulur ve uygulamaya kullanan tüm kullanıcılar bu instance’a erişirler. Haliyle birden fazla instance olma durumu olmaz. Farklı threadler aynı instance’a erişmeye çalışır. Belli durumlarda spring framework içindeki bean’lerden birden fazla instance oluşturulabilir. Örneğin bir alışveriş sepeti eklemesi yapılırken her kullanıcının eriştiği bağımsız bir instance olmalıdır. Bunun için de prototype scope kullanılır. Bunlar dışında request scope ya da session scope da kullanılır ihtiyaca göre.
İki farklı kullanıcının bir veritabanında aynı tablonun aynı satırına erişim sağladığını ve veritabanından aynı nesneyi(ikisi de memory’deki aynı nesneye erişiyor) aldığını varsayalım. Bu durumda bu nesneyi ‘shared object’ olarak düşünebiliriz. Yani iki kullanıcı farklı threadler üzerinden erişim sağlasa dahi aynı nesnenin synchronized methoduna erişmeye çalışacaktır. Haliyle nesne üzerindeki synchronization veri çatışmasını engellemeye ve atomicity’yi sağlamaya yardımcı olur. Burada synchronization bu iki thread’in nesneyi aynı anda güncellemeye çalışmasını(örneğin) engelleyecektir. Buradaki nesne veritabanında çekilmiş olan satırdır.

Load balancing bilgilendirmesi
Load balancing, performansı ve kullanılabilirli artırmak için request’leri birden çok sunucuya dağıtır. Load balancing pool içindeki her bir sunucunun veritabanıyla kendi bağlantısı olabilir. Bu da veritabanındaki aynı satır için farklı nesnelerin döndürülmesine neden olabilir. Veritabanı bağlantısı, load balancer pool içindeki sunucular arasında paylaşılsa dahi, dönen nesne her bir sunucu tarafından hafızada cache’lenmiş olabilir. Yani dönen nesnelerden birisi nesnenin cache copy’si olurken diğeri veritabanından dönen nesne olabilir.
Bu durumda iki kullanıcının aynı nesne üzerinde işlem yaptığından emin olmak için “shared cache” ya da “distributed cache” kullanılabilir.
Synchronized kullanımı programı yavaşlatabilir. Her şey için kullanılmamalıdır.
Lock Stratejileri
Locking(kilitleme): Veritabanındaki verinin okunması ve kullanılması arasında geçen sürede değişmesini engellemek için yapılan işlemlerdir.
Optimistic ve pessimistic kilitleme stratejileri bulunmaktadır.
Optimistic: Birden fazla transaction birbirlerini etkilemeden tamamlanabilir. Değiştirilecek veriye ulaşan transaction veriyi kilitlemeden işlemine devam eder. Commit işleminden önce herbir transaction verinin değiştirilip değiştirilmediğini kontrol eder. Veri okunduğu andaki haline göre değişim olduysa yani başka bir transaction veri üzerinde güncelleme yaptıysa, commit işlemi iptal edilir rollback yapılır.
Pessimistic: Transaction’ların birbirlerini etkileyeceği düşünülür. Bir transaction veriyi okuduğunda veri kilitlenir ve veri kullanım işlemi tamamlandığında kilit bırakılır.
Eşzamanlı veri güncelleme girişimlerinin az olmasının beklendiği durumlarda optimistic, çok olmasının beklendiği durumlarda pessimistic yaklaşım kullanılabilir. Pessimistic yaklaşım kullanılırken timeout süreleri belirleme deadlock oluşumlarını engellemede fayda sağlar.
optimistic approach -> satırı al (findById(Integer id)) (kilitleme yok ) -> Satır eğer değişmediyse güncelle.
pessimistic approach -> satırı al ve kilitle -> Güncelle.
Uygulama sunucuları genellikle her bir http isteği için, bu isteği işlemek üzere bir thread oluşturur. Aynı anda çok sayıda kullanıcı farklı threadler ile uygulamaya bağımsız olarak erişir. Sunucu tarafından bir thread pool oluşturulur. Connection pool’dan farklı olarak her bir veritabanı isteğinde değil her bir http requestinde thread oluşturulur.