Kata kunci Java Volatile
Dalam pemrosesan konkurensi Java Thread, ada banyak kebingungan dalam penggunaan kata kunci yang mudah menguap. Saya pikir menggunakan kata kunci ini dapat membuat semuanya berjalan dengan baik saat menggunakan pemrosesan konkurensi multi-threaded.
Bahasa Java mendukung multi-threading. Untuk menyelesaikan masalah konkurensi utas, blok sinkron dan mekanisme kata kunci yang mudah menguap diperkenalkan di dalam bahasa.
disinkronkan
Setiap orang terbiasa dengan blok yang disinkronkan, dan mereka diimplementasikan melalui kata kunci yang disinkronkan. Dengan pernyataan yang disinkronkan dan blok, hanya satu utas yang dapat menggunakannya secara bersamaan saat mengakses multi-thread.
Metode yang dimodifikasi atau blok kode yang disinkronkan.
tidak stabil
Untuk variabel yang dimodifikasi dengan volatil, utas akan membaca nilai variabel yang paling dimodifikasi setiap kali menggunakan variabel. Volatile mudah disalahgunakan dan digunakan untuk operasi atom.
Mari kita lihat contoh di bawah ini. Kami menerapkan penghitung. Setiap kali utas dimulai, metode Counter Inc akan dipanggil untuk menambahkan satu ke konter.
Lingkungan Eksekusi - Versi JDK: JDK1.6.0_31, Memori: 3G CPU: X86 2.4G
Counter kelas publik {public static int count = 0; public static void inc () {// penundaan di sini adalah 1 milidetik, membuat hasilnya jelas mencoba {thread.sleep (1); } catch (InterruptedException e) {} count ++; } public static void main (string [] args) {// Mulai 1000 utas pada saat yang sama untuk melakukan perhitungan i ++ dan melihat hasil aktual untuk (int i = 0; i <1000; i ++) {utas baru (runnable baru () {@Override void run () {counter.inc ();}}). } // Nilai setiap menjalankan di sini mungkin berbeda, mungkin 1000 System.out.println ("Jalankan hasil: counter.count =" + counter.count); }}运行结果:Counter.count= 995
实际运算结果每次可能都不一样,本机的结果为:运行结果:Counter.count= 995 ,可以看出,在多线程的环境下,Counter.count并没有期望结果是1000
Banyak orang berpikir bahwa ini adalah masalah konkurensi multi-utas. Anda hanya perlu menambahkan volatile很多人以为,这个是多线程并发问题,只需要在变量count之前加上就可以避免这个问题,那我们在修改代码看看,看看结果是不是符合我们的期望
penghitung kelas publik {public volatile static int count = 0; public static void inc () {// penundaan di sini adalah 1 milidetik, membuat hasilnya jelas mencoba {thread.sleep (1); } catch (InterruptedException e) {} count ++; } public static void main (string [] args) {// Mulai 1000 utas pada saat yang sama, lakukan perhitungan i ++, dan lihat hasil aktual untuk (int i = 0; i <1000; i ++) {utas baru (runnable baru () {@override void run () {counter.inc ();}} () {@override public run () {counter.inc ();}} () {@override public run () {counter.inc ();} () () {@Override public run () {counter. } // Nilai setiap menjalankan di sini mungkin berbeda, mungkin 1000 system.out.println ("Jalankan hasil: counter.count =" + counter.count); }}Hasil Menjalankan: Counter.Count = 992
Hasil operasi masih belum 1000 seperti yang kami harapkan. Mari kita analisis alasan di bawah ini
Dalam artikel koleksi sampah Java, alokasi memori pada saat JVM dijelaskan. Salah satu area memori adalah tumpukan mesin virtual JVM, dan setiap utas memiliki tumpukan utas saat berjalan.
Tumpukan utas menyimpan informasi nilai variabel selama runtime utas. Saat utas mengakses nilai objek tertentu, pertama -tama temukan nilai variabel yang sesuai dengan memori heap melalui referensi objek, dan kemudian letakkan memori heap
Nilai spesifik dari variabel dimuat ke dalam memori lokal utas dan salinan variabel dibuat. Setelah itu, utas tidak lagi memiliki hubungan dengan nilai variabel objek dalam memori heap, tetapi secara langsung memodifikasi nilai variabel salin.
Pada saat tertentu setelah modifikasi (sebelum utas keluar), nilai salinan variabel utas secara otomatis ditulis kembali ke variabel objek dalam heap. Dengan cara ini nilai objek di tumpukan akan berubah. Gambar berikut
Jelaskan interaksi penulisan ini
Baca dan Muat Variabel Salin Dari Memori Utama ke Memori Kerja Saat Ini
Gunakan dan Tetapkan Kode Etek untuk Mengubah Nilai Variabel Bersama
Simpan dan Tulis Refresh Konten Terkait Memori Utama dengan Data Memori Kerja
di mana penggunaan dan penetapan dapat muncul beberapa kali
Namun, operasi ini bukan atom, yaitu, setelah beban baca, jika variabel jumlah memori utama dimodifikasi, nilai dalam memori kerja utas tidak akan menyebabkan perubahan yang sesuai karena telah dimuat, sehingga hasil yang dihitung akan berbeda dari yang diharapkan.
Untuk variabel yang dimodifikasi dengan volatile, mesin virtual JVM hanya memastikan bahwa nilai yang dimuat dari memori utama ke memori yang berfungsi adalah yang terbaru adalah yang terbaru
Misalnya, jika utas 1 dan utas 2 melakukan operasi baca dan beban, dan temukan bahwa nilai jumlah dalam memori utama adalah 5, maka nilai terbaru akan dimuat
Setelah jumlah tumpukan dimodifikasi dalam utas 1, itu akan ditulis ke dalam memori utama, dan variabel hitungan dalam memori utama akan menjadi 6.
Karena Thread 2 telah melakukan operasi baca dan beban, nilai variabel dari jumlah memori utama juga akan diperbarui menjadi 6 setelah operasi.
Hal ini menyebabkan konkurensi terjadi setelah dua utas dimodifikasi dengan kata kunci yang mudah menguap dalam waktu.
Terima kasih telah membaca, saya harap ini dapat membantu Anda. Terima kasih atas dukungan Anda untuk situs ini!