Volatile vs Static di Jawa

Jawaban:

365

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 Objectsdibuat 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 Objectbidang, 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 concurrentMethodWrongsecara 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 AtomicIntegerkelas.

stivlo
sumber
7
Pengubah volatil menjamin bahwa utas apa pun yang membaca bidang akan melihat nilai yang paling baru ditulis, jadi itu perlu jika variabel dibagi di antara beberapa utas dan Anda memerlukan fitur ini, itu tergantung pada kasus penggunaan Anda.
stivlo
5
Apa cache ketika Anda mengatakan "cache lokal"? Cache CPU, semacam cache JVM?
mert inan
6
@mertinan ya, variabel bisa di cache lebih dekat ke prosesor atau inti. Lihat cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html untuk rincian lebih lanjut.
stivlo
15
'volatile' tidak menyiratkan 'satu variabel per objek'. Tidak adanya 'statis' melakukan itu. -1 karena gagal menjernihkan kesalahpahaman dasar ini pada bagian OP.
Marquis of Lorne
27
@ EJP Saya berpikir bahwa kalimat "Mendeklarasikan variabel sebagai volatile, akan ada satu variabel untuk setiap Objek. Jadi di permukaan sepertinya tidak ada perbedaan dari variabel normal" menjelaskan itu, saya telah menambahkan dan tidak statis , merasa bebas untuk mengedit artikel dan meningkatkan kata-kata untuk membuatnya lebih jelas.
stivlo
288

Perbedaan Antara Statis dan Volatil:

Variabel Statis : Jika dua Thread (misalkan t1dan t2) mengakses objek yang sama dan memperbarui variabel yang dinyatakan sebagai statis maka itu berarti t1dan t2dapat membuat salinan lokal mereka sendiri dari objek yang sama (termasuk variabel statis) di cache masing-masing, jadi perbarui dibuat oleh t1ke variabel statis di cache lokal tidak akan tercermin dalam variabel statis untuk t2cache.

Variabel statis digunakan dalam konteks Objek di mana pembaruan yang dibuat oleh satu objek akan mencerminkan semua objek lain dari kelas yang sama tetapi tidak dalam konteks Thread di mana pembaruan satu thread ke variabel statis akan mencerminkan perubahan segera ke semua utas (dalam cache lokal mereka).

Variabel yang mudah menguap : Jika dua Threads (kira t1dan t2) mengakses objek yang sama dan memperbarui variabel yang dinyatakan sebagai volatile maka itu berarti t1dan t2dapat membuat cache lokal mereka sendiri Objek kecuali variabel yang dinyatakan sebagai stabil . Jadi variabel volatil hanya akan memiliki satu salinan utama yang akan diperbarui oleh utas berbeda dan pembaruan yang dibuat oleh satu utas ke variabel volatil akan segera mencerminkan ke utas lainnya.

Som
sumber
6
Halo @Som, Tolong perbaiki saya jika saya salah. Tapi jangan Anda berpikir pernyataan " tetapi tidak dalam konteks Thread di mana pembaruan satu thread ke variabel statis akan mencerminkan perubahan segera ke semua utas (dalam cache lokal mereka). " Seharusnya "tetapi tidak dalam konteks dari Thread tempat pembaruan satu utas ke variabel statis akan <<NOT>> mencerminkan perubahan segera ke semua utas (dalam cache lokal mereka). "
Jaikrat
@ Jaikrat Ya itu sangat membingungkan bagi saya. Pemahaman saya adalah bahwa Anda benar dan bahwa jawaban ini salah, seperti yang tertulis. Saya juga ingin dikoreksi jika saya salah.
stuart
@Jaikrat Threads tidak menyimpan cache variabel statis tetapi, lihat variabel statis yang diperbarui.
Som
@Som Lalu apakah Anda ingin memperbaiki para dan menghapus tetapi tidak dalam konteks Thread . Itu sangat membingungkan. Terima kasih
Jaikrat
Sayangnya, jawaban ini salah. Pada CPU modern, bahkan sebuah volatilevariabel dapat dibagi di antara cache CPU yang berbeda. Ini tidak menimbulkan masalah karena cache menegosiasikan kepemilikan eksklusif dari baris cache sebelum memodifikasinya.
David Schwartz
32

Selain jawaban lain, saya ingin menambahkan satu gambar untuk itu (gambar membuat mudah dimengerti)

masukkan deskripsi gambar di sini

staticvariabel dapat di-cache untuk masing-masing utas. Di lingkungan multi-utas jika satu utas mengubah data yang di-cache, yang mungkin tidak mencerminkan utas lainnya karena mereka memiliki salinannya .

volatiledeklarasi memastikan bahwa utas tidak akan menyimpan data dan hanya menggunakan salinan yang dibagikan .

sumber gambar

mrsrinivas
sumber
1
variabel statis dibagi di antara objek di bawah utas? Ini harus membaca variabel statis dibagi di antara objek semua objek terlepas dari utas.
cquezel
1
"variabel volatil dibagi di antara banyak utas (jadi objek juga)." Volatile tidak mengubah bagaimana variabel dibagi di antara banyak utas atau objek. Ini mengubah cara runtime diizinkan untuk menyimpan nilai.
cquezel
1
Komentar Anda tentang variabel statis juga berlaku untuk non statis dan "akan di-cache" dan "tidak akan mencerminkan" mungkin harus diulang-ulang "mungkin di-cache" dan "mungkin tidak mencerminkan".
cquezel
4
Saya sangat bingung. gambar ini membersihkan semua pertanyaan saya!
vins
5

Saya berpikir staticdan volatiletidak memiliki hubungan sama sekali. Saya sarankan Anda membaca tutorial java untuk memahami Akses Atom , dan mengapa menggunakan akses atom, memahami apa yang disisipkan , Anda akan menemukan jawabannya.

Amitābha
sumber
4

Secara sederhana,

  1. static : staticvariabel dikaitkan dengan kelas , bukan dengan objek apa pun . Setiap instance kelas membagikan variabel kelas, yang berada di satu lokasi tetap dalam memori

  2. volatile : Kata kunci ini berlaku untuk variabel kelas dan instance .

Menggunakan variabel volatile mengurangi risiko kesalahan konsistensi memori, karena setiap penulisan ke variabel volatile menetapkan hubungan yang terjadi sebelum dengan membaca selanjutnya dari variabel yang sama. Ini berarti bahwa perubahan ke variabel volatil selalu terlihat oleh utas lainnya

Silahkan lihat pada ini artikel dengan Javin Paul memahami variabel volatile dalam cara yang lebih baik.

masukkan deskripsi gambar di sini

Dengan tidak adanya volatilekata kunci, nilai variabel di setiap tumpukan thread mungkin berbeda. Dengan membuat variabel sebagai volatile, semua utas akan mendapatkan nilai yang sama dalam memori kerja dan kesalahan konsistensi memori telah dihindari.

Di sini istilahnya variabledapat berupa staticvariabel (kelas) atau variabel instance(objek).

Mengenai kueri Anda:

Pokoknya nilai variabel statis juga akan menjadi satu nilai untuk semua utas, lalu mengapa kita memilih volatile?

Jika saya perlu instancevariabel dalam aplikasi saya, saya tidak bisa menggunakan staticvariabel. Bahkan dalam kasus staticvariabel, konsistensi tidak dijamin karena Thread cache seperti yang ditunjukkan pada diagram.

Menggunakan volatilevariabel mengurangi risiko kesalahan konsistensi memori, karena setiap penulisan ke variabel volatil membentuk hubungan yang terjadi sebelum dengan membaca selanjutnya dari variabel yang sama. Ini berarti bahwa perubahan ke variabel volatil selalu terlihat oleh utas lainnya.

Terlebih lagi, itu juga berarti bahwa ketika utas membaca variabel volatil, ia melihat tidak hanya perubahan terbaru ke volatil, tetapi juga efek samping dari kode yang menyebabkan perubahan => kesalahan konsistensi memori masih dimungkinkan dengan variabel volatil . Untuk menghindari efek samping, Anda harus menggunakan variabel yang disinkronkan. Tetapi ada solusi yang lebih baik di java.

Menggunakan akses variabel atom sederhana lebih efisien daripada mengakses variabel-variabel ini melalui kode yang disinkronkan

Beberapa kelas dalam java.util.concurrentpaket menyediakan metode atom yang tidak bergantung pada sinkronisasi.

Lihat artikel kontrol konkurensi tingkat tinggi ini untuk detail lebih lanjut.

Terutama melihat variabel Atom .

Pertanyaan SE terkait:

Volatile Vs Atomic

Volatile boolean vs AtomicBoolean

Perbedaan antara volatile dan disinkronkan di Jawa

Ravindra babu
sumber
Saya sangat menghargai jawaban ini. Aku tahu apa yang volatilesebelumnya, tetapi, jawaban ini memperjelas banyak bagi saya mengapa saya masih perlu menggunakan volatiledengan staticvariabel.
Chaklader Asfak Arefe
volatile: Kata kunci ini berlaku untuk variabel kelas dan instance. Pernyataan yang Anda katakan di atas tidak benar terkait dengan kelas. hanya dua kata kunci yang berlaku untuk variabel yang volatile dan sementara. jadi tidak stabil tidak berlaku untuk kelas.
ASR
volatile berlaku untuk variabel kelas (statis). Lihatlah tautan singleton terkunci ganda di google dan Anda dapat menemukan bahwa pemahaman Anda salah. stackoverflow.com/questions/18093735/…
Ravindra babu
private static volatile adalah deklarasi yang valid.
Ravindra babu
0

akses nilai variabel volatile akan langsung dari memori utama. Ini harus digunakan hanya dalam lingkungan multi-threading. variabel statis akan dimuat satu kali. Jika digunakan dalam lingkungan utas tunggal, bahkan jika salinan variabel akan diperbarui dan tidak akan ada salahnya mengaksesnya karena hanya ada satu utas.

Sekarang jika variabel statis digunakan dalam lingkungan multi-threading maka akan ada masalah jika seseorang mengharapkan hasil yang diinginkan darinya. Karena setiap utas memiliki salinannya sendiri maka setiap kenaikan atau penurunan pada variabel statis dari satu utas mungkin tidak tercermin dalam utas lainnya.

jika seseorang mengharapkan hasil yang diinginkan dari variabel statis kemudian gunakan volatile dengan statis dalam multi-threading maka semuanya akan teratasi.

Aslam anwer
sumber
0

Tidak yakin variabel statis di-cache di memori lokal thread atau TIDAK. Tetapi ketika saya mengeksekusi dua utas (T1, T2) mengakses objek yang sama (obj) dan ketika pembaruan yang dilakukan oleh utas T1 ke variabel statis itu tercermin di T2.

pengguna2779355
sumber
-2

Jika kita mendeklarasikan variabel sebagai statis, hanya akan ada satu salinan variabel. Jadi, setiap kali thread berbeda mengakses variabel itu, hanya akan ada satu nilai akhir untuk variabel (karena hanya ada satu lokasi memori yang dialokasikan untuk variabel).

Jika suatu variabel dinyatakan volatil, semua utas akan memiliki salinan variabel sendiri tetapi nilainya diambil dari memori utama. Jadi, nilai variabel di semua utas akan sama.

Jadi, dalam kedua kasus, titik utama adalah bahwa nilai variabel sama di semua utas.

Jitendra Nalwaya
sumber
15
Jika variabel dinyatakan sebagai volatile, semua utas akan memiliki salinan variabel sendiri tetapi nilainya diambil dari memori utama. => benar. Jadi, nilai variabel di semua utas akan sama. => salah, setiap utas akan menggunakan nilai yang sama untuk Objek yang sama, tetapi setiap Obyek akan memiliki salinannya sendiri.
stivlo