Java necə işləyir

Mövzu seç, kod yaz və daxildə nə baş verdiyini addım-addım gör.

Memory

Collection-lar

Concurrency

Dil və JVM

Mövzular

Thread-lər

Race condition: count++

Hər thread-in öz stack-i var, heap isə ortaqdır. count heap-dədir, r isə stack-də.

count++ tək əməliyyat deyil: oxu, artır, yaz. İki thread eyni dəyəri oxusa, biri o birinin nəticəsinin üstünə yazır.

Növbəti düyməsi hazır sıranı göstərir. Thread düymələri ilə sıranı özün seç: hansı sırada itki olmur?

synchronized

synchronized bir object-in monitor lock-unu alır. Eyni lock-u eyni anda yalnız bir thread saxlaya bilər, o biri BLOCKED olur.

İndi thread B-ni A-nın ortasına sal: B irəliləyə bilmir, ona görə üç addım bir yerdə işləyir.

Lock həm də görünməni təmin edir: lock-u alan thread əvvəlki sahibin yazdıqlarını görür. Qiyməti gözləmədir, lock-u mümkün qədər qısa saxla.

volatile count++-ı düzəltmir

volatile hər oxumanın ən son yazılmış dəyəri görməsini təmin edir. Amma oxu, artır, yaz yenə üç ayrı addımdır.

Fərqə bax: eyni sıra, eyni itki. volatile atomicity vermir.

volatile bir thread yazır, başqaları oxuyur olan hallar üçündür: növbəti bölmələrdəki running flag-i kimi.

CAS və AtomicInteger

AtomicInteger lock işlətmir. CAS, yəni compare-and-swap, hardware-in tək addımda etdiyi işdir: dəyər gözlədiyim kimidirsə, yenisini yaz, deyilsə, heç nə etmə.

Uğursuz olan thread gözləmir, yenidən oxuyub cəhd edir. Thread-lər BLOCKED olmur.

Sıx rəqabətdə çox təkrar ola bilər. Çox yazılan sayğac üçün LongAdder də var.

Deadlock

Thread A a-nı, B b-ni alır. Sonra A b-ni, B a-nı istəyir. İkisi də əbədi gözləyir, Java bunu özü həll etmir.

Ən sadə həll: bütün thread-lər lock-ları eyni sırada alsın. Düymə ilə sıranı dəyiş və yenidən işə sal.

Real proqramda jstack deadlock-u tapıb göstərir.

Görünmə: volatile flag

Bir thread-in yazdığını o biri nə vaxt görür? Sinxronizasiya yoxdursa, Java zəmanət vermir.

Bu dövrədə worker running-i oxuyur. JIT dəyərin dəyişmədiyini fərz edib yenidən oxumaya bilər, thread əbədi fırlanır.

volatile, synchronized və Thread.start/join happens-before yaradır, yəni görünməyə zəmanət verir.

Thread vəziyyətləri

Thread.getState() altı dəyərdən birini qaytarır. Bu, thread dump oxuyanda ən çox lazım olan cədvəldir.

Tələ: RUNNABLE “indi CPU-dadır” demək deyil. I/O gözləyən thread də çox vaxt RUNNABLE görünür.