Poin penting tentang volatile
:
- Sinkronisasi di Jawa dimungkinkan dengan menggunakan kata kunci
synchronized
dan volatile
dan kunci Java .
- Di Jawa, kita tidak bisa memiliki
synchronized
variabel. Menggunakan synchronized
kata kunci dengan variabel adalah ilegal dan akan menghasilkan kesalahan kompilasi. Alih-alih menggunakan synchronized
variabel di Jawa, Anda bisa menggunakan volatile
variabel java , yang akan menginstruksikan thread JVM untuk membaca nilai volatile
variabel dari memori utama dan jangan cache secara lokal.
- Jika suatu variabel tidak dibagi di antara beberapa utas, maka tidak perlu menggunakan
volatile
kata kunci.
sumber
Contoh penggunaan volatile
:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
Kami membuat contoh dengan malas pada saat permintaan pertama datang.
Jika kita tidak membuat _instance
variabel volatile
maka Thread yang membuat instance dari Singleton
tidak dapat berkomunikasi ke thread lain. Jadi jika Thread A membuat Singleton instance dan setelah penciptaan, CPU rusak dll, semua utas lainnya tidak akan dapat melihat nilai _instance
bukan nol dan mereka akan percaya itu masih ditugaskan nol.
Mengapa ini terjadi? Karena utas pembaca tidak melakukan penguncian dan sampai utas penulis keluar dari blok yang disinkronkan, memori tidak akan disinkronkan dan nilai _instance
tidak akan diperbarui di memori utama. Dengan kata kunci Volatile di Java, ini ditangani oleh Java sendiri dan pembaruan tersebut akan terlihat oleh semua utas pembaca.
Kesimpulan : volatile
kata kunci juga digunakan untuk mengkomunikasikan konten memori antara utas.
Contoh penggunaan tanpa volatile:
public class Singleton{
private static Singleton _instance; //without volatile variable
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
Kode di atas tidak aman untuk thread. Meskipun memeriksa nilai instance sekali lagi di dalam blok yang disinkronkan (untuk alasan kinerja), kompiler JIT dapat mengatur ulang bytecode sedemikian rupa sehingga referensi ke instance diatur sebelum konstruktor menyelesaikan eksekusi. Ini berarti metode getInstance () mengembalikan objek yang mungkin belum diinisialisasi sepenuhnya. Untuk membuat kode-aman, kata kunci volatile dapat digunakan sejak Java 5 untuk variabel instan. Variabel yang ditandai sebagai volatil hanya dapat dilihat oleh utas lainnya setelah konstruktor objek telah menyelesaikan eksekusi sepenuhnya.
Sumber
volatile
penggunaan di Jawa :
Iterator gagal-cepat biasanya diimplementasikan menggunakan volatile
penghitung pada objek daftar.
- Ketika daftar diperbarui, penghitung bertambah.
- Ketika sebuah
Iterator
dibuat, nilai saat ini dari penghitung tertanam di Iterator
objek.
- Ketika
Iterator
operasi dilakukan, metode ini membandingkan dua nilai penghitung dan melempar a ConcurrentModificationException
jika mereka berbeda.
Implementasi iterator gagal-aman biasanya ringan. Mereka biasanya mengandalkan properti dari struktur data implementasi daftar tertentu. Tidak ada pola umum.
volatile
yang datang dengan Java Memory Model baru yang didefinisikan dalam JSR 133: bahwa ketika sebuah thread membaca sebuahvolatile
variabel, ia melihat tidak hanya nilai yang terakhir ditulis untuknya oleh beberapa thread lain, tetapi juga semua yang lain menulis ke variabel lain yang terlihat di utas lainnya pada saatvolatile
penulisan. Lihat jawaban ini dan referensi ini .