Mendeklarasikan variabel statis di Jawa, berarti hanya akan ada satu salinan, tidak peduli berapa banyak objek kelas yang dibuat. Variabel akan dapat diakses bahkan tanpa Objects
dibuat sama sekali. Namun, utas mungkin memiliki nilai cached lokal untuknya.
Ketika suatu variabel volatile dan tidak statis , akan ada satu variabel untuk masing-masing Object
. Jadi, di permukaan sepertinya tidak ada perbedaan dari variabel normal tetapi sama sekali berbeda dari statis . Namun, bahkan dengan Object
bidang, utas dapat menembolok nilai variabel secara lokal.
Ini berarti bahwa jika dua utas memperbarui variabel dari Obyek yang sama secara bersamaan, dan variabel tidak dinyatakan volatil, mungkin ada kasus di mana salah satu utas memiliki cache dalam nilai lama.
Bahkan jika Anda mengakses nilai statis melalui beberapa utas, setiap utas dapat memiliki salinan dalam tembolok lokal! Untuk menghindari ini, Anda dapat mendeklarasikan variabel sebagai volatile statis dan ini akan memaksa utas untuk membaca setiap kali nilai global.
Namun, volatile bukanlah pengganti sinkronisasi yang tepat!
Misalnya:
private static volatile int counter = 0;
private void concurrentMethodWrong() {
counter = counter + 5;
//do something
counter = counter - 5;
}
Menjalankan concurrentMethodWrong
secara bersamaan berkali-kali dapat menyebabkan nilai akhir counter berbeda dari nol!
Untuk mengatasi masalah, Anda harus menerapkan kunci:
private static final Object counterLock = new Object();
private static volatile int counter = 0;
private void concurrentMethodRight() {
synchronized (counterLock) {
counter = counter + 5;
}
//do something
synchronized (counterLock) {
counter = counter - 5;
}
}
Atau gunakan AtomicInteger
kelas.