Saya yakin pembaca yang memahami multi-threading Java akan mengetahui perannya dengan jelas. Kata kunci volatil digunakan untuk mendeklarasikan variabel tipe sederhana, seperti int, float, boolean dan tipe data lainnya. Jika tipe data sederhana ini dinyatakan volatil, operasi pada tipe data tersebut menjadi atomik. Namun hal ini mempunyai keterbatasan tertentu. Misalnya, n dalam contoh berikut bukan atomik:
Copy kode kodenya sebagai berikut:
paket mitos;
JoinThread kelas publik memperluas Thread
{
int volatil statis publik n = 0;
menjalankan kekosongan publik()
{
untuk (int saya = 0; saya < 10; saya++)
mencoba
{
n = n + 1;
sleep(3); // Untuk membuat hasil lari lebih acak, tunda 3 milidetik
}
tangkapan (Pengecualian e)
{
}
}
public static void main(String[] args) memunculkan Pengecualian
{
Utas utas[] = Utas baru[100];
for (int i = 0; i < benang.panjang; i++)
// Buat 100 thread
thread[i] = new JoinThread();
for (int i = 0; i < benang.panjang; i++)
//Jalankan 100 thread yang baru saja dibuat
benang[i].mulai();
for (int i = 0; i < benang.panjang; i++)
//Lanjutkan setelah 100 thread dieksekusi
utas[i].join();
Sistem.keluar.println("n=" + JoinThread.n);
}
}
Jika operasi pada n bersifat atomik, hasil keluaran akhir seharusnya n=1000. Namun, saat menjalankan kode area di atas, keluaran n seringkali kurang dari 1000, yang menunjukkan bahwa n=n+1 bukan operasi tingkat atom. . Alasannya adalah untuk variabel sederhana yang dinyatakan volatil, jika nilai saat ini terkait dengan nilai variabel sebelumnya, maka kata kunci volatil tidak berpengaruh, artinya ekspresi berikut bukan operasi atom:
Copy kode kodenya sebagai berikut:
n = n + 1;
n++;
Jika Anda ingin menjadikan situasi ini operasi atom, Anda perlu menggunakan kata kunci tersinkronisasi. Kode di atas dapat diubah ke bentuk berikut:
Copy kode kodenya sebagai berikut:
paket mitos;
JoinThread kelas publik memperluas Thread
{
int statis publik n = 0;
kekosongan publik yang disinkronkan statis inc()
{
n++;
}
menjalankan kekosongan publik()
{
untuk (int saya = 0; saya < 10; saya++)
mencoba
{
inc(); // n = n + 1 diubah menjadi inc();
sleep(3); // Untuk membuat hasil lari lebih acak, tunda 3 milidetik
}
tangkapan (Pengecualian e)
{
}
}
public static void main(String[] args) memunculkan Pengecualian
{
Utas utas[] = Utas baru[100];
for (int i = 0; i < benang.panjang; i++)
// Buat 100 thread
thread[i] = new JoinThread();
for (int i = 0; i < benang.panjang; i++)
//Jalankan 100 thread yang baru saja dibuat
benang[i].mulai();
for (int i = 0; i < benang.panjang; i++)
//Lanjutkan setelah 100 thread dieksekusi
utas[i].join();
Sistem.keluar.println("n=" + JoinThread.n);
}
}
Kode di atas mengubah n=n+1 menjadi inc(), dimana metode inc menggunakan kata kunci sinkronisasi untuk sinkronisasi metode. Oleh karena itu, berhati-hatilah saat menggunakan kata kunci volatil. Ini tidak berarti bahwa variabel bertipe sederhana diubah dengan volatil. Semua operasi pada variabel ini adalah operasi asli ketika nilai variabel ditentukan oleh operasi sebelumnya, seperti n= n+1 , n++, dll., kata kunci volatil akan menjadi tidak valid. Operasi pada variabel adalah tingkat atom hanya jika nilai variabel tidak ada hubungannya dengan nilai sebelumnya adalah level aslinya. Oleh karena itu, Anda harus berhati-hati saat menggunakan kunci volatil. Jika Anda tidak yakin, Anda dapat menggunakan kunci tersinkronisasi dan bukan kunci volatil.