Soalan: Bolehkah disegerakkan dan tidur juga mencapai tujuan keterlihatan benang yang tidak menentu Penerangan masalah umum adalah seperti berikut:
pakej com.test;
import java.util.concurrent.TimeUnit;
ujian kelas awam1 {
boolean statik peribadi ialah = benar;
public static void main(String[] args) {
Thread baharu(New Runnable() {
@Override
public void run() {
int i = 0;
while(test1.is){
i++;
1 //disegerakkan (ini) { } akan menyegarkan semula nilai pembolehubah memori utama ke susunan benang secara paksa?
2 //System.out.println("1"); println disegerakkan dan akan menyegarkan semula nilai pembolehubah memori utama ke susunan benang?
3 //sleep akan memuatkan semula nilai memori utama?
// cuba {
// TimeUnit.MICROSECONDS.sleep(1);
// }tangkap (InterruptedException e) {
// e.printStackTrace();
// }
}
}
}).mula();
cuba {
TimeUnit.SECONDS.sleep(1);
} tangkapan (InterruptedException e) {
e.printStackTrace();
}
Thread baharu(New Runnable() {
@Override
public void run() {
is = false; //Tetapkan kepada false supaya utas di atas menamatkan gelung while
}
}).mula();
}
}
S: Mengapakah keseluruhan program tidak ditamatkan? Mengapa program ditamatkan apabila anda menyahkomen mana-mana blok kod (1, 2, 3)? Adakah disegerakkan secara paksa menyegarkan nilai pembolehubah memori ke timbunan benang Apakah yang akan dilakukan oleh tidur?
Melibatkan penerangan pengetahuan
meruap: Kata kunci ini memastikan keterlihatan pembolehubah dalam utas Semua utas yang mengakses pembolehubah yang diubah suai oleh meruap mesti membaca dari memori utama sebelum beroperasi, dan menulis kembali ke memori utama serta-merta selepas memori kerja diubah suai, memastikan bahawa utas lain Visibility, the. kata kunci dengan kesan yang sama adalah muktamad.
disegerakkan: Semua operasi penyegerakan mesti memastikan 1. atomicity 2. keterlihatan, jadi perubahan yang berlaku dalam blok disegerakkan akan segera ditulis kembali ke memori utama
tidur: Kaedah ini hanya akan melepaskan masa pelaksanaan CPU dan tidak akan melepaskan kunci.
Analisis Masalah
S1: Mengapa program tidak ditamatkan selepas mengulas kod?
A1: Oleh kerana nilai pembolehubah boolean is=true dimuatkan ke dalam memori kerjanya sendiri oleh thread sebelumnya (dirujuk sebagai thread A), selepas thread berikutnya (dirujuk sebagai thread B) menukar boolean is=false, ia mungkin tidak ditulis ke memori utama dengan serta-merta (tetapi Dalam soalan ini, ia harus ditulis ke ingatan utama dengan serta-merta, kerana benang akan keluar selepas melaksanakan is=false Walaupun ia ditulis ke memori utama serta-merta, benang A mungkin tidak dimuatkan ke dalam ingatan kerja serta-merta, supaya program diteruskan Bukankah ia akan ditamatkan? Inilah yang kebanyakan kita fikirkan, tetapi sebenarnya, JVM telah dioptimumkan sebahagian besarnya untuk tahap perkakasan semasa, pada asasnya memastikan penyegerakan memori kerja dan memori utama yang tepat pada masanya pada tahap yang besar, yang bersamaan dengan menggunakan tidak menentu. secara lalai. Tetapi hanya pada tahap maksimum! Apabila sumber CPU sentiasa diduduki, penyegerakan antara memori kerja dan memori utama, iaitu, keterlihatan pembolehubah tidak akan begitu tepat pada masanya! Kesimpulannya akan disahkan kemudian.
S2: Mengapa program ditamatkan hanya apabila mana-mana blok kod (1, 2, 3) tidak dikomen?
A2: Kod dengan nombor baris 1 dan 2 mempunyai ciri yang sama, iaitu, semuanya melibatkan kunci penyegerakan yang disegerakkan Jadi, seperti yang diagak oleh pengarang soalan, akan menyegerakkan secara paksa nilai pembolehubah dalam memori utama ke dalam. susunan benang? , dan kaedah tidur juga akan menyegarkan nilai pembolehubah dalam memori utama ke susunan benang? Malah, kami berkata sebelum ini bahawa disegerakkan hanya akan memastikan keterlihatan pembolehubah dalam blok disegerakkan, dan pembolehubah is tidak berada dalam blok disegerakkan, jadi ia jelas tidak disebabkan oleh ini. Seterusnya kita tambah kod berikut selepas kod i++;:
untuk(int k=0;k<100000;k++){
Objek baharu();
}
Jika anda menjalankannya semula, program akan ditamatkan serta-merta! kenapa? Dalam A1 di atas, kami telah mengatakan bahawa walaupun dengan pengoptimuman JVM, apabila CPU sentiasa diduduki, keterlihatan data tidak dapat dijamin dengan baik, sama seperti program di atas terus menggelung untuk melakukan operasi i++ dan mengapa program itu berhenti selepas menambah kod di atas? Kerana untuk sebilangan besar operasi Object() baharu, CPU bukan lagi operasi memakan masa utama yang memakan masa sebenar harus berada dalam peruntukan memori (kerana kelajuan pemprosesan CPU jelas lebih cepat daripada memori. , jika tidak, tidak akan ada daftar CPU ), jadi selepas CPU melahu, ia akan mengikuti penanda aras pengoptimuman JVM untuk memastikan keterlihatan data secepat mungkin, dengan itu menyegerakkan pembolehubah dari memori utama ke memori kerja, akhirnya membawa kepada penghujung program Inilah sebabnya kaedah sleep() tidak melibatkan operasi penyegerakan , tetapi program masih boleh ditamatkan, kerana kaedah sleep() akan melepaskan CPU tetapi bukan kunci.
Atas ialah kandungan terperinci Contoh analisis masalah keterlihatan pembolehubah Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!